From 36c49e3f258dced101949edabd72e9bc3f1dedc4 Mon Sep 17 00:00:00 2001
From: dim <dim@FreeBSD.org>
Date: Fri, 17 Sep 2010 15:54:40 +0000
Subject: Vendor import of clang r114020 (from the release_28 branch):
 http://llvm.org/svn/llvm-project/cfe/branches/release_28@114020

Approved by:	rpaulo (mentor)
---
 lib/Checker/AdjustedReturnValueChecker.cpp     |   3 +-
 lib/Checker/AggExprVisitor.cpp                 |  11 +-
 lib/Checker/AnalysisConsumer.cpp               |  12 +-
 lib/Checker/AnalysisManager.cpp                |  31 ++
 lib/Checker/ArrayBoundChecker.cpp              |   2 +-
 lib/Checker/BasicObjCFoundationChecks.cpp      |   5 +-
 lib/Checker/BasicStore.cpp                     |  63 +--
 lib/Checker/BasicValueFactory.cpp              |  32 +-
 lib/Checker/BugReporter.cpp                    |  51 +-
 lib/Checker/BugReporterVisitors.cpp            |  49 +-
 lib/Checker/CFRefCount.cpp                     | 202 ++------
 lib/Checker/CMakeLists.txt                     |   4 +-
 lib/Checker/CStringChecker.cpp                 | 594 ++++++++++++++++++++--
 lib/Checker/CallAndMessageChecker.cpp          |   2 +-
 lib/Checker/CallInliner.cpp                    |  54 --
 lib/Checker/CastSizeChecker.cpp                |   4 +
 lib/Checker/CheckDeadStores.cpp                |   4 +-
 lib/Checker/CheckSecuritySyntaxOnly.cpp        |  16 +-
 lib/Checker/CheckerHelpers.cpp                 |  80 +++
 lib/Checker/CocoaConventions.cpp               |   5 +-
 lib/Checker/DivZeroChecker.cpp                 |   8 +-
 lib/Checker/Environment.cpp                    |  41 +-
 lib/Checker/FixedAddressChecker.cpp            |   2 +-
 lib/Checker/FlatStore.cpp                      |  82 +--
 lib/Checker/GRCXXExprEngine.cpp                |  34 +-
 lib/Checker/GRCoreEngine.cpp                   | 154 ++++--
 lib/Checker/GRExprEngine.cpp                   | 678 +++++++++++++++----------
 lib/Checker/GRExprEngineExperimentalChecks.cpp |  16 +-
 lib/Checker/GRExprEngineExperimentalChecks.h   |   5 +-
 lib/Checker/GRState.cpp                        | 224 +++++++-
 lib/Checker/IdempotentOperationChecker.cpp     | 673 ++++++++++++++++--------
 lib/Checker/LLVMConventionsChecker.cpp         |   1 -
 lib/Checker/Makefile                           |   1 -
 lib/Checker/MallocChecker.cpp                  | 251 +++++++--
 lib/Checker/MemRegion.cpp                      |  69 ++-
 lib/Checker/OSAtomicChecker.cpp                |   8 +-
 lib/Checker/PointerArithChecker.cpp            |   3 +-
 lib/Checker/PointerSubChecker.cpp              |   2 +-
 lib/Checker/RangeConstraintManager.cpp         |   1 -
 lib/Checker/RegionStore.cpp                    | 356 +++++--------
 lib/Checker/ReturnPointerRangeChecker.cpp      |   2 +-
 lib/Checker/ReturnUndefChecker.cpp             |   1 +
 lib/Checker/SVals.cpp                          |   7 +-
 lib/Checker/SValuator.cpp                      |   4 +-
 lib/Checker/SimpleConstraintManager.cpp        |  70 +--
 lib/Checker/SimpleConstraintManager.h          |   4 -
 lib/Checker/SimpleSValuator.cpp                | 284 ++++++-----
 lib/Checker/StackAddrLeakChecker.cpp           |   2 +-
 lib/Checker/Store.cpp                          |  41 +-
 lib/Checker/StreamChecker.cpp                  | 197 ++++++-
 lib/Checker/SymbolManager.cpp                  | 139 +++--
 lib/Checker/UndefBranchChecker.cpp             |  17 +-
 lib/Checker/UndefinedAssignmentChecker.cpp     |  12 +-
 lib/Checker/UnixAPIChecker.cpp                 |   2 +-
 lib/Checker/UnreachableCodeChecker.cpp         | 226 +++++++++
 lib/Checker/VLASizeChecker.cpp                 |   2 +-
 lib/Checker/ValueManager.cpp                   |  17 +-
 57 files changed, 3348 insertions(+), 1512 deletions(-)
 create mode 100644 lib/Checker/AnalysisManager.cpp
 delete mode 100644 lib/Checker/CallInliner.cpp
 create mode 100644 lib/Checker/CheckerHelpers.cpp
 create mode 100644 lib/Checker/UnreachableCodeChecker.cpp

(limited to 'lib/Checker')

diff --git a/lib/Checker/AdjustedReturnValueChecker.cpp b/lib/Checker/AdjustedReturnValueChecker.cpp
index b92f2e7..0ed04fb 100644
--- a/lib/Checker/AdjustedReturnValueChecker.cpp
+++ b/lib/Checker/AdjustedReturnValueChecker.cpp
@@ -70,8 +70,7 @@ void AdjustedReturnValueChecker::PostVisitCallExpr(CheckerContext &C,
   }
   else if (const BlockDataRegion *BD = dyn_cast<BlockDataRegion>(callee)) {
     const BlockTextRegion *BR = BD->getCodeRegion();
-    const BlockPointerType *BT =
-      BR->getLocationType(C.getASTContext())->getAs<BlockPointerType>();
+    const BlockPointerType *BT=BR->getLocationType()->getAs<BlockPointerType>();
     const FunctionType *FT = BT->getPointeeType()->getAs<FunctionType>();
     actualResultTy = FT->getResultType();
   }
diff --git a/lib/Checker/AggExprVisitor.cpp b/lib/Checker/AggExprVisitor.cpp
index 343afec..6d472f4 100644
--- a/lib/Checker/AggExprVisitor.cpp
+++ b/lib/Checker/AggExprVisitor.cpp
@@ -18,6 +18,13 @@
 using namespace clang;
 
 namespace {
+/// AggExprVisitor is designed after AggExprEmitter of the CodeGen module.  It
+/// is used for evaluating exprs of C++ object type. Evaluating such exprs
+/// requires a destination pointer pointing to the object being evaluated
+/// into. Passing such a pointer around would pollute the Visit* interface of
+/// GRExprEngine. AggExprVisitor encapsulates code that goes through various
+/// cast and construct exprs (and others), and at the final point, dispatches
+/// back to the GRExprEngine to let the real evaluation logic happen.
 class AggExprVisitor : public StmtVisitor<AggExprVisitor> {
   SVal DestPtr;
   ExplodedNode *Pred;
@@ -38,8 +45,8 @@ void AggExprVisitor::VisitCastExpr(CastExpr *E) {
   switch (E->getCastKind()) {
   default: 
     assert(0 && "Unhandled cast kind");
-  case CastExpr::CK_NoOp:
-  case CastExpr::CK_ConstructorConversion:
+  case CK_NoOp:
+  case CK_ConstructorConversion:
     Visit(E->getSubExpr());
     break;
   }
diff --git a/lib/Checker/AnalysisConsumer.cpp b/lib/Checker/AnalysisConsumer.cpp
index 524f37e..ad5ccb50 100644
--- a/lib/Checker/AnalysisConsumer.cpp
+++ b/lib/Checker/AnalysisConsumer.cpp
@@ -29,6 +29,7 @@
 #include "clang/Checker/PathSensitive/GRTransferFuncs.h"
 #include "clang/Checker/PathDiagnosticClients.h"
 #include "GRExprEngineExperimentalChecks.h"
+#include "GRExprEngineInternalChecks.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Frontend/AnalyzerOptions.h"
@@ -173,10 +174,12 @@ public:
     Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
                                   PP.getLangOptions(), PD,
                                   CreateStoreMgr, CreateConstraintMgr,
+                                  /* Indexer */ 0, 
                                   Opts.MaxNodes, Opts.MaxLoop,
                                   Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
                                   Opts.PurgeDead, Opts.EagerlyAssume,
-                                  Opts.TrimGraph, Opts.InlineCall));
+                                  Opts.TrimGraph, Opts.InlineCall,
+                                  Opts.UnoptimizedCFG));
   }
 
   virtual void HandleTranslationUnit(ASTContext &C);
@@ -341,7 +344,10 @@ static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr,
   if (C.Opts.EnableExperimentalChecks)
     RegisterExperimentalChecks(Eng);
 
-  if (C.Opts.EnableIdempotentOperationChecker)
+  // Enable idempotent operation checking if it was explicitly turned on, or if
+  // we are running experimental checks (i.e. everything)
+  if (C.Opts.IdempotentOps || C.Opts.EnableExperimentalChecks
+      || C.Opts.EnableExperimentalInternalChecks)
     RegisterIdempotentOperationChecker(Eng);
 
   // Set the graph auditor.
@@ -352,7 +358,7 @@ static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr,
   }
 
   // Execute the worklist algorithm.
-  Eng.ExecuteWorkList(mgr.getStackFrame(D), mgr.getMaxNodes());
+  Eng.ExecuteWorkList(mgr.getStackFrame(D, 0), mgr.getMaxNodes());
 
   // Release the auditor (if any) so that it doesn't monitor the graph
   // created BugReporter.
diff --git a/lib/Checker/AnalysisManager.cpp b/lib/Checker/AnalysisManager.cpp
new file mode 100644
index 0000000..339cdab
--- /dev/null
+++ b/lib/Checker/AnalysisManager.cpp
@@ -0,0 +1,31 @@
+//===-- AnalysisManager.cpp -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Checker/PathSensitive/AnalysisManager.h"
+#include "clang/Index/Entity.h"
+#include "clang/Index/Indexer.h"
+
+using namespace clang;
+
+const AnalysisContext *
+AnalysisManager::getAnalysisContextInAnotherTU(const Decl *D) {
+  idx::Entity Ent = idx::Entity::get(const_cast<Decl *>(D), 
+                                     Idxer->getProgram());
+  FunctionDecl *FuncDef;
+  idx::TranslationUnit *TU;
+  llvm::tie(FuncDef, TU) = Idxer->getDefinitionFor(Ent);
+
+  if (FuncDef == 0)
+    return 0;
+
+  // This AnalysisContext wraps function definition in another translation unit.
+  // But it is still owned by the AnalysisManager associated with the current
+  // translation unit.
+  return AnaCtxMgr.getContext(FuncDef, TU);
+}
diff --git a/lib/Checker/ArrayBoundChecker.cpp b/lib/Checker/ArrayBoundChecker.cpp
index 746b3f9..98345bd 100644
--- a/lib/Checker/ArrayBoundChecker.cpp
+++ b/lib/Checker/ArrayBoundChecker.cpp
@@ -58,7 +58,7 @@ void ArrayBoundChecker::VisitLocation(CheckerContext &C, const Stmt *S, SVal l){
   // Get the size of the array.
   DefinedOrUnknownSVal NumElements 
     = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(), 
-                                         ER->getValueType(C.getASTContext()));
+                                            ER->getValueType());
 
   const GRState *StInBound = state->AssumeInBound(Idx, NumElements, true);
   const GRState *StOutBound = state->AssumeInBound(Idx, NumElements, false);
diff --git a/lib/Checker/BasicObjCFoundationChecks.cpp b/lib/Checker/BasicObjCFoundationChecks.cpp
index ecb2d1c..3c1a6d1 100644
--- a/lib/Checker/BasicObjCFoundationChecks.cpp
+++ b/lib/Checker/BasicObjCFoundationChecks.cpp
@@ -73,9 +73,6 @@ class BasicObjCFoundationChecks : public GRSimpleAPICheck {
   bool isNSString(const ObjCInterfaceType *T, llvm::StringRef suffix);
   bool AuditNSString(ExplodedNode* N, const ObjCMessageExpr* ME);
 
-  void Warn(ExplodedNode* N, const Expr* E, const std::string& s);
-  void WarnNilArg(ExplodedNode* N, const Expr* E);
-
   bool CheckNilArg(ExplodedNode* N, unsigned Arg);
 
 public:
@@ -358,7 +355,7 @@ bool AuditCFNumberCreate::Audit(ExplodedNode* N,GRStateManager&){
   if (!R)
     return false;
 
-  QualType T = Ctx.getCanonicalType(R->getValueType(Ctx));
+  QualType T = Ctx.getCanonicalType(R->getValueType());
 
   // FIXME: If the pointee isn't an integer type, should we flag a warning?
   //  People can do weird stuff with pointers.
diff --git a/lib/Checker/BasicStore.cpp b/lib/Checker/BasicStore.cpp
index 62c8d9c..f82e1b2 100644
--- a/lib/Checker/BasicStore.cpp
+++ b/lib/Checker/BasicStore.cpp
@@ -52,7 +52,7 @@ public:
   Store InvalidateRegions(Store store, const MemRegion * const *Begin,
                           const MemRegion * const *End, const Expr *E,
                           unsigned Count, InvalidatedSymbols *IS,
-                          bool invalidateGlobals);
+                          bool invalidateGlobals, InvalidatedRegions *Regions);
 
   Store scanForIvars(Stmt *B, const Decl* SelfDecl,
                      const MemRegion *SelfRegion, Store St);
@@ -61,11 +61,6 @@ public:
   Store Remove(Store St, Loc loc);
   Store getInitialStore(const LocationContext *InitLoc);
 
-  // FIXME: Investigate what is using this. This method should be removed.
-  virtual Loc getLoc(const VarDecl* VD, const LocationContext *LC) {
-    return ValMgr.makeLoc(MRMgr.getVarRegion(VD, LC));
-  }
-
   Store BindCompoundLiteral(Store store, const CompoundLiteralExpr*,
                             const LocationContext*, SVal val) {
     return store;
@@ -77,9 +72,8 @@ public:
 
   /// RemoveDeadBindings - Scans a BasicStore of 'state' for dead values.
   ///  It updatees the GRState object in place with the values removed.
-  const GRState *RemoveDeadBindings(GRState &state,
-                                    const StackFrameContext *LCtx,
-                                    SymbolReaper& SymReaper,
+  Store RemoveDeadBindings(Store store, const StackFrameContext *LCtx,
+                           SymbolReaper& SymReaper,
                           llvm::SmallVectorImpl<const MemRegion*>& RegionRoots);
 
   void iterBindings(Store store, BindingsHandler& f);
@@ -103,8 +97,6 @@ public:
 
 private:
   SVal LazyRetrieve(Store store, const TypedRegion *R);
-
-  ASTContext& getContext() { return StateMgr.getContext(); }
 };
 
 } // end anonymous namespace
@@ -228,17 +220,15 @@ Store BasicStoreManager::Bind(Store store, Loc loc, SVal V) {
     return VBFactory.Add(B, R, V).getRoot();
   }
 
-  ASTContext &C = StateMgr.getContext();
-
   // Special case: handle store of pointer values (Loc) to pointers via
   // a cast to intXX_t*, void*, etc.  This is needed to handle
   // OSCompareAndSwap32Barrier/OSCompareAndSwap64Barrier.
   if (isa<Loc>(V) || isa<nonloc::LocAsInteger>(V))
     if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
       // FIXME: Should check for index 0.
-      QualType T = ER->getLocationType(C);
+      QualType T = ER->getLocationType();
 
-      if (isHigherOrderRawPtr(T, C))
+      if (isHigherOrderRawPtr(T, Ctx))
         R = ER->getSuperRegion();
     }
 
@@ -249,7 +239,7 @@ Store BasicStoreManager::Bind(Store store, Loc loc, SVal V) {
 
   // Do not bind to arrays.  We need to explicitly check for this so that
   // we do not encounter any weirdness of trying to load/store from arrays.
-  if (TyR->isBoundable() && TyR->getValueType(C)->isArrayType())
+  if (TyR->isBoundable() && TyR->getValueType()->isArrayType())
     return store;
 
   if (nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(&V)) {
@@ -259,7 +249,7 @@ Store BasicStoreManager::Bind(Store store, Loc loc, SVal V) {
     // a pointer.  We may wish to flag a type error here if the types
     // are incompatible.  This may also cause lots of breakage
     // elsewhere. Food for thought.
-    if (TyR->isBoundable() && Loc::IsLocType(TyR->getValueType(C)))
+    if (TyR->isBoundable() && Loc::IsLocType(TyR->getValueType()))
       V = X->getLoc();
   }
 
@@ -285,12 +275,11 @@ Store BasicStoreManager::Remove(Store store, Loc loc) {
   }
 }
 
-const GRState *BasicStoreManager::RemoveDeadBindings(GRState &state,
+Store BasicStoreManager::RemoveDeadBindings(Store store,
                                             const StackFrameContext *LCtx,
                                             SymbolReaper& SymReaper,
                            llvm::SmallVectorImpl<const MemRegion*>& RegionRoots)
 {
-  Store store = state.getStore();
   BindingsTy B = GetBindings(store);
   typedef SVal::symbol_iterator symbol_iterator;
 
@@ -365,8 +354,7 @@ const GRState *BasicStoreManager::RemoveDeadBindings(GRState &state,
     }
   }
 
-  state.setStore(store);
-  return StateMgr.getPersistentState(state);
+  return store;
 }
 
 Store BasicStoreManager::scanForIvars(Stmt *B, const Decl* SelfDecl,
@@ -406,10 +394,10 @@ Store BasicStoreManager::getInitialStore(const LocationContext *InitLoc) {
   Store St = VBFactory.GetEmptyMap().getRoot();
 
   for (LVDataTy::decl_iterator I=D.begin_decl(), E=D.end_decl(); I != E; ++I) {
-    NamedDecl* ND = const_cast<NamedDecl*>(I->first);
+    const NamedDecl* ND = I->first;
 
     // Handle implicit parameters.
-    if (ImplicitParamDecl* PD = dyn_cast<ImplicitParamDecl>(ND)) {
+    if (const ImplicitParamDecl* PD = dyn_cast<ImplicitParamDecl>(ND)) {
       const Decl& CD = *InitLoc->getDecl();
       if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(&CD)) {
         if (MD->getSelfDecl() == PD) {
@@ -449,11 +437,11 @@ Store BasicStoreManager::BindDeclInternal(Store store, const VarRegion* VR,
     // will not be called more than once.
 
     // Static global variables should not be visited here.
-    assert(!(VD->getStorageClass() == VarDecl::Static &&
+    assert(!(VD->getStorageClass() == SC_Static &&
              VD->isFileVarDecl()));
 
     // Process static variables.
-    if (VD->getStorageClass() == VarDecl::Static) {
+    if (VD->getStorageClass() == SC_Static) {
       // C99: 6.7.8 Initialization
       //  If an object that has static storage duration is not initialized
       //  explicitly, then:
@@ -465,12 +453,9 @@ Store BasicStoreManager::BindDeclInternal(Store store, const VarRegion* VR,
         if (Loc::IsLocType(T))
           store = Bind(store, loc::MemRegionVal(VR),
                        loc::ConcreteInt(BasicVals.getValue(0, T)));
-        else if (T->isIntegerType())
+        else if (T->isIntegerType() && T->isScalarType())
           store = Bind(store, loc::MemRegionVal(VR),
                        nonloc::ConcreteInt(BasicVals.getValue(0, T)));
-        else {
-          // assert(0 && "ignore other types of variables");
-        }
       } else {
         store = Bind(store, loc::MemRegionVal(VR), *InitVal);
       }
@@ -478,7 +463,8 @@ Store BasicStoreManager::BindDeclInternal(Store store, const VarRegion* VR,
   } else {
     // Process local scalar variables.
     QualType T = VD->getType();
-    if (ValMgr.getSymbolManager().canSymbolicate(T)) {
+    // BasicStore only supports scalars.
+    if (T->isScalarType() && ValMgr.getSymbolManager().canSymbolicate(T)) {
       SVal V = InitVal ? *InitVal : UndefinedVal();
       store = Bind(store, loc::MemRegionVal(VR), V);
     }
@@ -523,11 +509,12 @@ StoreManager::BindingsHandler::~BindingsHandler() {}
 
 
 Store BasicStoreManager::InvalidateRegions(Store store,
-                                      const MemRegion * const *I,
-                                      const MemRegion * const *End,
-                                      const Expr *E, unsigned Count,
-                                      InvalidatedSymbols *IS,
-                                      bool invalidateGlobals) {
+                                           const MemRegion * const *I,
+                                           const MemRegion * const *End,
+                                           const Expr *E, unsigned Count,
+                                           InvalidatedSymbols *IS,
+                                           bool invalidateGlobals,
+                                           InvalidatedRegions *Regions) {
   if (invalidateGlobals) {
     BindingsTy B = GetBindings(store);
     for (BindingsTy::iterator I=B.begin(), End=B.end(); I != End; ++I) {
@@ -545,6 +532,8 @@ Store BasicStoreManager::InvalidateRegions(Store store,
         continue;
     }
     store = InvalidateRegion(store, *I, E, Count, IS);
+    if (Regions)
+      Regions->push_back(R);
   }
 
   // FIXME: This is copy-and-paste from RegionStore.cpp.
@@ -558,6 +547,8 @@ Store BasicStoreManager::InvalidateRegions(Store store,
                                   Count);
 
     store = Bind(store, loc::MemRegionVal(GS), V);
+    if (Regions)
+      Regions->push_back(GS);
   }
 
   return store;
@@ -582,7 +573,7 @@ Store BasicStoreManager::InvalidateRegion(Store store,
     }
   }
 
-  QualType T = cast<TypedRegion>(R)->getValueType(R->getContext());
+  QualType T = cast<TypedRegion>(R)->getValueType();
   SVal V = ValMgr.getConjuredSymbolVal(R, E, T, Count);
   return Bind(store, loc::MemRegionVal(R), V);
 }
diff --git a/lib/Checker/BasicValueFactory.cpp b/lib/Checker/BasicValueFactory.cpp
index 246beea..4c9b109 100644
--- a/lib/Checker/BasicValueFactory.cpp
+++ b/lib/Checker/BasicValueFactory.cpp
@@ -149,22 +149,22 @@ BasicValueFactory::EvaluateAPSInt(BinaryOperator::Opcode Op,
     default:
       assert (false && "Invalid Opcode.");
 
-    case BinaryOperator::Mul:
+    case BO_Mul:
       return &getValue( V1 * V2 );
 
-    case BinaryOperator::Div:
+    case BO_Div:
       return &getValue( V1 / V2 );
 
-    case BinaryOperator::Rem:
+    case BO_Rem:
       return &getValue( V1 % V2 );
 
-    case BinaryOperator::Add:
+    case BO_Add:
       return &getValue( V1 + V2 );
 
-    case BinaryOperator::Sub:
+    case BO_Sub:
       return &getValue( V1 - V2 );
 
-    case BinaryOperator::Shl: {
+    case BO_Shl: {
 
       // FIXME: This logic should probably go higher up, where we can
       // test these conditions symbolically.
@@ -182,7 +182,7 @@ BasicValueFactory::EvaluateAPSInt(BinaryOperator::Opcode Op,
       return &getValue( V1.operator<<( (unsigned) Amt ));
     }
 
-    case BinaryOperator::Shr: {
+    case BO_Shr: {
 
       // FIXME: This logic should probably go higher up, where we can
       // test these conditions symbolically.
@@ -200,33 +200,33 @@ BasicValueFactory::EvaluateAPSInt(BinaryOperator::Opcode Op,
       return &getValue( V1.operator>>( (unsigned) Amt ));
     }
 
-    case BinaryOperator::LT:
+    case BO_LT:
       return &getTruthValue( V1 < V2 );
 
-    case BinaryOperator::GT:
+    case BO_GT:
       return &getTruthValue( V1 > V2 );
 
-    case BinaryOperator::LE:
+    case BO_LE:
       return &getTruthValue( V1 <= V2 );
 
-    case BinaryOperator::GE:
+    case BO_GE:
       return &getTruthValue( V1 >= V2 );
 
-    case BinaryOperator::EQ:
+    case BO_EQ:
       return &getTruthValue( V1 == V2 );
 
-    case BinaryOperator::NE:
+    case BO_NE:
       return &getTruthValue( V1 != V2 );
 
       // Note: LAnd, LOr, Comma are handled specially by higher-level logic.
 
-    case BinaryOperator::And:
+    case BO_And:
       return &getValue( V1 & V2 );
 
-    case BinaryOperator::Or:
+    case BO_Or:
       return &getValue( V1 | V2 );
 
-    case BinaryOperator::Xor:
+    case BO_Xor:
       return &getValue( V1 ^ V2 );
   }
 }
diff --git a/lib/Checker/BugReporter.cpp b/lib/Checker/BugReporter.cpp
index 0422d80..bffbd52 100644
--- a/lib/Checker/BugReporter.cpp
+++ b/lib/Checker/BugReporter.cpp
@@ -94,8 +94,8 @@ static const Stmt* GetNextStmt(const ExplodedNode* N) {
         case Stmt::ChooseExprClass:
         case Stmt::ConditionalOperatorClass: continue;
         case Stmt::BinaryOperatorClass: {
-          BinaryOperator::Opcode Op = cast<BinaryOperator>(S)->getOpcode();
-          if (Op == BinaryOperator::LAnd || Op == BinaryOperator::LOr)
+          BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode();
+          if (Op == BO_LAnd || Op == BO_LOr)
             continue;
           break;
         }
@@ -177,18 +177,9 @@ public:
   }
 
   virtual NodeMapClosure& getNodeResolver() { return NMC; }
-  BugReport& getReport() { return *R; }
 
   PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S);
 
-  PathDiagnosticLocation
-  getEnclosingStmtLocation(const PathDiagnosticLocation &L) {
-    if (const Stmt *S = L.asStmt())
-      return getEnclosingStmtLocation(S);
-
-    return L;
-  }
-
   PathDiagnosticClient::PathGenerationScheme getGenerationScheme() const {
     return PDC ? PDC->getGenerationScheme() : PathDiagnosticClient::Extensive;
   }
@@ -541,9 +532,9 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
     ProgramPoint P = N->getLocation();
 
     if (const BlockEdge* BE = dyn_cast<BlockEdge>(&P)) {
-      CFGBlock* Src = BE->getSrc();
-      CFGBlock* Dst = BE->getDst();
-      Stmt* T = Src->getTerminator();
+      const CFGBlock* Src = BE->getSrc();
+      const CFGBlock* Dst = BE->getDst();
+      const Stmt* T = Src->getTerminator();
 
       if (!T)
         continue;
@@ -577,7 +568,7 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
           std::string sbuf;
           llvm::raw_string_ostream os(sbuf);
 
-          if (Stmt* S = Dst->getLabel()) {
+          if (const Stmt* S = Dst->getLabel()) {
             PathDiagnosticLocation End(S, SMgr);
 
             switch (S->getStmtClass()) {
@@ -593,17 +584,17 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
 
               case Stmt::CaseStmtClass: {
                 os << "Control jumps to 'case ";
-                CaseStmt* Case = cast<CaseStmt>(S);
-                Expr* LHS = Case->getLHS()->IgnoreParenCasts();
+                const CaseStmt* Case = cast<CaseStmt>(S);
+                const Expr* LHS = Case->getLHS()->IgnoreParenCasts();
 
                 // Determine if it is an enum.
                 bool GetRawInt = true;
 
-                if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(LHS)) {
+                if (const DeclRefExpr* DR = dyn_cast<DeclRefExpr>(LHS)) {
                   // FIXME: Maybe this should be an assertion.  Are there cases
                   // were it is not an EnumConstantDecl?
-                  EnumConstantDecl* D =
-                  dyn_cast<EnumConstantDecl>(DR->getDecl());
+                  const EnumConstantDecl* D =
+                    dyn_cast<EnumConstantDecl>(DR->getDecl());
 
                   if (D) {
                     GetRawInt = false;
@@ -668,12 +659,12 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
           if (!PDB.supportsLogicalOpControlFlow())
             break;
 
-          BinaryOperator *B = cast<BinaryOperator>(T);
+          const BinaryOperator *B = cast<BinaryOperator>(T);
           std::string sbuf;
           llvm::raw_string_ostream os(sbuf);
           os << "Left side of '";
 
-          if (B->getOpcode() == BinaryOperator::LAnd) {
+          if (B->getOpcode() == BO_LAnd) {
             os << "&&" << "' is ";
 
             if (*(Src->succ_begin()+1) == Dst) {
@@ -692,7 +683,7 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
             }
           }
           else {
-            assert(B->getOpcode() == BinaryOperator::LOr);
+            assert(B->getOpcode() == BO_LOr);
             os << "||" << "' is ";
 
             if (*(Src->succ_begin()+1) == Dst) {
@@ -902,8 +893,6 @@ class EdgeBuilder {
     CLocs.pop_back();
   }
 
-  PathDiagnosticLocation IgnoreParens(const PathDiagnosticLocation &L);
-
 public:
   EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb)
     : PD(pd), PDB(pdb) {
@@ -935,10 +924,6 @@ public:
 
   void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false);
 
-  void addEdge(const Stmt *S, bool alwaysAdd = false) {
-    addEdge(PathDiagnosticLocation(S, PDB.getSourceManager()), alwaysAdd);
-  }
-
   void rawAddEdge(PathDiagnosticLocation NewLoc);
 
   void addContext(const Stmt *S);
@@ -1006,14 +991,6 @@ bool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container,
            SM.getInstantiationColumnNumber(ContainerREnd)));
 }
 
-PathDiagnosticLocation
-EdgeBuilder::IgnoreParens(const PathDiagnosticLocation &L) {
-  if (const Expr* E = dyn_cast_or_null<Expr>(L.asStmt()))
-      return PathDiagnosticLocation(E->IgnoreParenCasts(),
-                                    PDB.getSourceManager());
-  return L;
-}
-
 void EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) {
   if (!PrevLoc.isValid()) {
     PrevLoc = NewLoc;
diff --git a/lib/Checker/BugReporterVisitors.cpp b/lib/Checker/BugReporterVisitors.cpp
index 776e12b..91cf349 100644
--- a/lib/Checker/BugReporterVisitors.cpp
+++ b/lib/Checker/BugReporterVisitors.cpp
@@ -31,7 +31,7 @@ const Stmt *clang::bugreporter::GetDerefExpr(const ExplodedNode *N) {
   const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
 
   if (const UnaryOperator *U = dyn_cast<UnaryOperator>(S)) {
-    if (U->getOpcode() == UnaryOperator::Deref)
+    if (U->getOpcode() == UO_Deref)
       return U->getSubExpr()->IgnoreParenCasts();
   }
   else if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) {
@@ -143,10 +143,9 @@ public:
 
         if (isa<loc::ConcreteInt>(V)) {
           bool b = false;
-          ASTContext &C = BRC.getASTContext();
           if (R->isBoundable()) {
             if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {
-              if (TR->getValueType(C)->isObjCObjectPointerType()) {
+              if (TR->getValueType()->isObjCObjectPointerType()) {
                 os << "initialized to nil";
                 b = true;
               }
@@ -174,10 +173,9 @@ public:
     if (os.str().empty()) {
       if (isa<loc::ConcreteInt>(V)) {
         bool b = false;
-        ASTContext &C = BRC.getASTContext();
         if (R->isBoundable()) {
           if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {
-            if (TR->getValueType(C)->isObjCObjectPointerType()) {
+            if (TR->getValueType()->isObjCObjectPointerType()) {
               os << "nil object reference stored to ";
               b = true;
             }
@@ -209,7 +207,7 @@ public:
     ProgramPoint P = N->getLocation();
 
     if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
-      CFGBlock *BSrc = BE->getSrc();
+      const CFGBlock *BSrc = BE->getSrc();
       S = BSrc->getTerminatorCondition();
     }
     else if (PostStmt *PS = dyn_cast<PostStmt>(&P)) {
@@ -282,7 +280,7 @@ public:
       ProgramPoint P = N->getLocation();
 
       if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
-        CFGBlock *BSrc = BE->getSrc();
+        const CFGBlock *BSrc = BE->getSrc();
         S = BSrc->getTerminatorCondition();
       }
       else if (PostStmt *PS = dyn_cast<PostStmt>(&P)) {
@@ -421,3 +419,40 @@ public:
 void clang::bugreporter::registerNilReceiverVisitor(BugReporterContext &BRC) {
   BRC.addVisitor(new NilReceiverVisitor());
 }
+
+// Registers every VarDecl inside a Stmt with a last store vistor.
+void clang::bugreporter::registerVarDeclsLastStore(BugReporterContext &BRC,
+                                                   const void *stmt,
+                                                   const ExplodedNode *N) {
+  const Stmt *S = static_cast<const Stmt *>(stmt);
+
+  std::deque<const Stmt *> WorkList;
+
+  WorkList.push_back(S);
+
+  while (!WorkList.empty()) {
+    const Stmt *Head = WorkList.front();
+    WorkList.pop_front();
+
+    GRStateManager &StateMgr = BRC.getStateManager();
+    const GRState *state = N->getState();
+
+    if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) {
+      if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+        const VarRegion *R =
+        StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
+
+        // What did we load?
+        SVal V = state->getSVal(S);
+
+        if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)) {
+          ::registerFindLastStore(BRC, R, V);
+        }
+      }
+    }
+
+    for (Stmt::const_child_iterator I = Head->child_begin();
+        I != Head->child_end(); ++I)
+      WorkList.push_back(*I);
+  }
+}
diff --git a/lib/Checker/CFRefCount.cpp b/lib/Checker/CFRefCount.cpp
index 3c74cd8..6fa48b2 100644
--- a/lib/Checker/CFRefCount.cpp
+++ b/lib/Checker/CFRefCount.cpp
@@ -82,8 +82,7 @@ public:
 
 static const ObjCMethodDecl*
 ResolveToInterfaceMethodDecl(const ObjCMethodDecl *MD) {
-  ObjCInterfaceDecl *ID =
-    const_cast<ObjCInterfaceDecl*>(MD->getClassInterface());
+  const ObjCInterfaceDecl *ID = MD->getClassInterface();
 
   return MD->isInstanceMethod()
          ? ID->lookupInstanceMethod(MD->getSelector())
@@ -93,11 +92,11 @@ ResolveToInterfaceMethodDecl(const ObjCMethodDecl *MD) {
 namespace {
 class GenericNodeBuilder {
   GRStmtNodeBuilder *SNB;
-  Stmt *S;
+  const Stmt *S;
   const void *tag;
   GREndPathNodeBuilder *ENB;
 public:
-  GenericNodeBuilder(GRStmtNodeBuilder &snb, Stmt *s,
+  GenericNodeBuilder(GRStmtNodeBuilder &snb, const Stmt *s,
                      const void *t)
   : SNB(&snb), S(s), tag(t), ENB(0) {}
 
@@ -195,12 +194,6 @@ public:
   static RetEffect MakeNoRet() {
     return RetEffect(NoRet);
   }
-
-  void Profile(llvm::FoldingSetNodeID& ID) const {
-    ID.AddInteger((unsigned)K);
-    ID.AddInteger((unsigned)O);
-    ID.AddInteger(index);
-  }
 };
 
 //===----------------------------------------------------------------------===//
@@ -239,9 +232,6 @@ private:
   RefVal(Kind k, RetEffect::ObjKind o, unsigned cnt, unsigned acnt, QualType t)
   : kind(k), okind(o), Cnt(cnt), ACnt(acnt), T(t) {}
 
-  RefVal(Kind k, unsigned cnt = 0)
-  : kind(k), okind(RetEffect::AnyObj), Cnt(cnt), ACnt(0) {}
-
 public:
   Kind getKind() const { return kind; }
 
@@ -256,12 +246,6 @@ public:
 
   QualType getType() const { return T; }
 
-  // Useful predicates.
-
-  static bool isError(Kind k) { return k >= ERROR_START; }
-
-  static bool isLeak(Kind k) { return k >= ERROR_LEAK_START; }
-
   bool isOwned() const {
     return getKind() == Owned;
   }
@@ -278,11 +262,6 @@ public:
     return getKind() == ReturnedNotOwned;
   }
 
-  bool isNonLeakError() const {
-    Kind k = getKind();
-    return isError(k) && !isLeak(k);
-  }
-
   static RefVal makeOwned(RetEffect::ObjKind o, QualType t,
                           unsigned Count = 1) {
     return RefVal(Owned, o, Count, 0, t);
@@ -474,11 +453,6 @@ public:
     DefaultArgEffect = E;
   }
 
-  /// setArg - Set the argument effect on the argument specified by idx.
-  void setArgEffect(ArgEffects::Factory& AF, unsigned idx, ArgEffect E) {
-    Args = AF.Add(Args, idx, E);
-  }
-
   /// getRetEffect - Returns the effect on the return value of the call.
   RetEffect getRetEffect() const { return Ret; }
 
@@ -492,28 +466,6 @@ public:
   /// getReceiverEffect - Returns the effect on the receiver of the call.
   ///  This is only meaningful if the summary applies to an ObjCMessageExpr*.
   ArgEffect getReceiverEffect() const { return Receiver; }
-
-  /// setReceiverEffect - Set the effect on the receiver of the call.
-  void setReceiverEffect(ArgEffect E) { Receiver = E; }
-
-  typedef ArgEffects::iterator ExprIterator;
-
-  ExprIterator begin_args() const { return Args.begin(); }
-  ExprIterator end_args()   const { return Args.end(); }
-
-  static void Profile(llvm::FoldingSetNodeID& ID, ArgEffects A,
-                      RetEffect RetEff, ArgEffect DefaultEff,
-                      ArgEffect ReceiverEff, bool EndPath) {
-    ID.Add(A);
-    ID.Add(RetEff);
-    ID.AddInteger((unsigned) DefaultEff);
-    ID.AddInteger((unsigned) ReceiverEff);
-    ID.AddInteger((unsigned) EndPath);
-  }
-
-  void Profile(llvm::FoldingSetNodeID& ID) const {
-    Profile(ID, Args, Ret, DefaultArgEffect, Receiver, EndPath);
-  }
 };
 } // end anonymous namespace
 
@@ -618,11 +570,6 @@ public:
     return Summ;
   }
 
-
-  RetainSummary* find(Expr* Receiver, Selector S) {
-    return find(getReceiverDecl(Receiver), S);
-  }
-
   RetainSummary* find(IdentifierInfo* II, Selector S) {
     // FIXME: Class method lookup.  Right now we dont' have a good way
     // of going between IdentifierInfo* and the class hierarchy.
@@ -634,47 +581,6 @@ public:
     return I == M.end() ? NULL : I->second;
   }
 
-  const ObjCInterfaceDecl* getReceiverDecl(Expr* E) {
-    if (const ObjCObjectPointerType* PT =
-        E->getType()->getAs<ObjCObjectPointerType>())
-      return PT->getInterfaceDecl();
-
-    return NULL;
-  }
-
-  RetainSummary*& operator[](ObjCMessageExpr* ME) {
-
-    Selector S = ME->getSelector();
-
-    const ObjCInterfaceDecl* OD = 0;
-    bool IsInstanceMessage = false;
-    switch (ME->getReceiverKind()) {
-    case ObjCMessageExpr::Instance:
-      OD = getReceiverDecl(ME->getInstanceReceiver());
-      IsInstanceMessage = true;
-      break;
-
-    case ObjCMessageExpr::SuperInstance:
-      IsInstanceMessage = true;
-      OD = ME->getSuperType()->getAs<ObjCObjectPointerType>()
-                                                        ->getInterfaceDecl();
-      break;
-
-    case ObjCMessageExpr::Class:
-      OD = ME->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
-      break;
-
-    case ObjCMessageExpr::SuperClass:
-      OD = ME->getSuperType()->getAs<ObjCObjectType>()->getInterface();
-      break;
-    }
-
-    if (IsInstanceMessage)
-      return OD ? M[ObjCSummaryKey(OD->getIdentifier(), S)] : M[S];
-
-    return M[ObjCSummaryKey(OD->getIdentifier(), S)];
-  }
-
   RetainSummary*& operator[](ObjCSummaryKey K) {
     return M[K];
   }
@@ -696,7 +602,7 @@ class RetainSummaryManager {
   //  Typedefs.
   //==-----------------------------------------------------------------==//
 
-  typedef llvm::DenseMap<FunctionDecl*, RetainSummary*>
+  typedef llvm::DenseMap<const FunctionDecl*, RetainSummary*>
           FuncSummariesTy;
 
   typedef ObjCSummaryCache ObjCMethodSummariesTy;
@@ -766,9 +672,10 @@ public:
 
   RetainSummary* getUnarySummary(const FunctionType* FT, UnaryFuncKind func);
 
-  RetainSummary* getCFSummaryCreateRule(FunctionDecl* FD);
-  RetainSummary* getCFSummaryGetRule(FunctionDecl* FD);
-  RetainSummary* getCFCreateGetRuleSummary(FunctionDecl* FD, StringRef FName);
+  RetainSummary* getCFSummaryCreateRule(const FunctionDecl* FD);
+  RetainSummary* getCFSummaryGetRule(const FunctionDecl* FD);
+  RetainSummary* getCFCreateGetRuleSummary(const FunctionDecl* FD, 
+                                           StringRef FName);
 
   RetainSummary* getPersistentSummary(ArgEffects AE, RetEffect RetEff,
                                       ArgEffect ReceiverEff = DoNothing,
@@ -796,12 +703,6 @@ public:
   void InitializeClassMethodSummaries();
   void InitializeMethodSummaries();
 private:
-
-  void addClsMethSummary(IdentifierInfo* ClsII, Selector S,
-                         RetainSummary* Summ) {
-    ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
-  }
-
   void addNSObjectClsMethSummary(Selector S, RetainSummary *Summ) {
     ObjCClassMethodSummaries[S] = Summ;
   }
@@ -892,7 +793,7 @@ public:
 
   ~RetainSummaryManager();
 
-  RetainSummary* getSummary(FunctionDecl* FD);
+  RetainSummary* getSummary(const FunctionDecl* FD);
 
   RetainSummary *getInstanceMethodSummary(const ObjCMessageExpr *ME,
                                           const GRState *state,
@@ -999,15 +900,15 @@ RetainSummaryManager::getPersistentSummary(ArgEffects AE, RetEffect RetEff,
 // Summary creation for functions (largely uses of Core Foundation).
 //===----------------------------------------------------------------------===//
 
-static bool isRetain(FunctionDecl* FD, StringRef FName) {
+static bool isRetain(const FunctionDecl* FD, StringRef FName) {
   return FName.endswith("Retain");
 }
 
-static bool isRelease(FunctionDecl* FD, StringRef FName) {
+static bool isRelease(const FunctionDecl* FD, StringRef FName) {
   return FName.endswith("Release");
 }
 
-RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
+RetainSummary* RetainSummaryManager::getSummary(const FunctionDecl* FD) {
   // Look up a summary in our cache of FunctionDecls -> Summaries.
   FuncSummariesTy::iterator I = FuncSummaries.find(FD);
   if (I != FuncSummaries.end())
@@ -1201,7 +1102,7 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
 }
 
 RetainSummary*
-RetainSummaryManager::getCFCreateGetRuleSummary(FunctionDecl* FD,
+RetainSummaryManager::getCFCreateGetRuleSummary(const FunctionDecl* FD,
                                                 StringRef FName) {
 
   if (FName.find("Create") != StringRef::npos ||
@@ -1250,7 +1151,8 @@ RetainSummaryManager::getUnarySummary(const FunctionType* FT,
   }
 }
 
-RetainSummary* RetainSummaryManager::getCFSummaryCreateRule(FunctionDecl* FD) {
+RetainSummary* 
+RetainSummaryManager::getCFSummaryCreateRule(const FunctionDecl* FD) {
   assert (ScratchArgs.isEmpty());
 
   if (FD->getIdentifier() == CFDictionaryCreateII) {
@@ -1261,7 +1163,8 @@ RetainSummary* RetainSummaryManager::getCFSummaryCreateRule(FunctionDecl* FD) {
   return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true));
 }
 
-RetainSummary* RetainSummaryManager::getCFSummaryGetRule(FunctionDecl* FD) {
+RetainSummary* 
+RetainSummaryManager::getCFSummaryGetRule(const FunctionDecl* FD) {
   assert (ScratchArgs.isEmpty());
   return getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::CF),
                               DoNothing, DoNothing);
@@ -1767,7 +1670,7 @@ private:
 
   void ProcessNonLeakError(ExplodedNodeSet& Dst,
                            GRStmtNodeBuilder& Builder,
-                           Expr* NodeExpr, SourceRange ErrorRange,
+                           const Expr* NodeExpr, SourceRange ErrorRange,
                            ExplodedNode* Pred,
                            const GRState* St,
                            RefVal::Kind hasErr, SymbolRef Sym);
@@ -1810,33 +1713,26 @@ public:
   void EvalSummary(ExplodedNodeSet& Dst,
                    GRExprEngine& Eng,
                    GRStmtNodeBuilder& Builder,
-                   Expr* Ex,
+                   const Expr* Ex,
                    InstanceReceiver Receiver,
                    const RetainSummary& Summ,
                    const MemRegion *Callee,
-                   ExprIterator arg_beg, ExprIterator arg_end,
+                   ConstExprIterator arg_beg, ConstExprIterator arg_end,
                    ExplodedNode* Pred, const GRState *state);
 
   virtual void EvalCall(ExplodedNodeSet& Dst,
                         GRExprEngine& Eng,
                         GRStmtNodeBuilder& Builder,
-                        CallExpr* CE, SVal L,
+                        const CallExpr* CE, SVal L,
                         ExplodedNode* Pred);
 
 
   virtual void EvalObjCMessageExpr(ExplodedNodeSet& Dst,
                                    GRExprEngine& Engine,
                                    GRStmtNodeBuilder& Builder,
-                                   ObjCMessageExpr* ME,
+                                   const ObjCMessageExpr* ME,
                                    ExplodedNode* Pred,
                                    const GRState *state);
-
-  bool EvalObjCMessageExprAux(ExplodedNodeSet& Dst,
-                              GRExprEngine& Engine,
-                              GRStmtNodeBuilder& Builder,
-                              ObjCMessageExpr* ME,
-                              ExplodedNode* Pred);
-
   // Stores.
   virtual void EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val);
 
@@ -1861,7 +1757,7 @@ public:
   virtual void EvalReturn(ExplodedNodeSet& Dst,
                           GRExprEngine& Engine,
                           GRStmtNodeBuilder& Builder,
-                          ReturnStmt* S,
+                          const ReturnStmt* S,
                           ExplodedNode* Pred);
 
   // Assumptions.
@@ -1934,7 +1830,6 @@ namespace {
   public:
 
     CFRefCount& getTF() { return TF; }
-    const CFRefCount& getTF() const { return TF; }
 
     // FIXME: Eventually remove.
     virtual const char* getDescription() const = 0;
@@ -2049,9 +1944,6 @@ namespace {
     CFRefBug& getBugType() {
       return (CFRefBug&) RangedBugReport::getBugType();
     }
-    const CFRefBug& getBugType() const {
-      return (const CFRefBug&) RangedBugReport::getBugType();
-    }
 
     virtual void getRanges(const SourceRange*& beg, const SourceRange*& end) {
       if (!getBugType().isLeak())
@@ -2605,11 +2497,12 @@ static QualType GetReturnType(const Expr* RetE, ASTContext& Ctx) {
 void CFRefCount::EvalSummary(ExplodedNodeSet& Dst,
                              GRExprEngine& Eng,
                              GRStmtNodeBuilder& Builder,
-                             Expr* Ex,
+                             const Expr* Ex,
                              InstanceReceiver Receiver,
                              const RetainSummary& Summ,
                              const MemRegion *Callee,
-                             ExprIterator arg_beg, ExprIterator arg_end,
+                             ConstExprIterator arg_beg, 
+                             ConstExprIterator arg_end,
                              ExplodedNode* Pred, const GRState *state) {
 
   // Evaluate the effect of the arguments.
@@ -2620,19 +2513,25 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst,
 
   llvm::SmallVector<const MemRegion*, 10> RegionsToInvalidate;
 
-  for (ExprIterator I = arg_beg; I != arg_end; ++I, ++idx) {
+  // HACK: Symbols that have ref-count state that are referenced directly
+  //  (not as structure or array elements, or via bindings) by an argument
+  //  should not have their ref-count state stripped after we have
+  //  done an invalidation pass.
+  llvm::DenseSet<SymbolRef> WhitelistedSymbols;
+
+  for (ConstExprIterator I = arg_beg; I != arg_end; ++I, ++idx) {
     SVal V = state->getSValAsScalarOrLoc(*I);
     SymbolRef Sym = V.getAsLocSymbol();
 
     if (Sym)
       if (RefBindings::data_type* T = state->get<RefBindings>(Sym)) {
+        WhitelistedSymbols.insert(Sym);
         state = Update(state, Sym, *T, Summ.getArg(idx), hasErr);
         if (hasErr) {
           ErrorRange = (*I)->getSourceRange();
           ErrorSym = Sym;
           break;
         }
-        continue;
       }
 
   tryAgain:
@@ -2703,22 +2602,22 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst,
   //  expression (the context) and the expression itself.  This should
   //  disambiguate conjured symbols.
   unsigned Count = Builder.getCurrentBlockCount();
-  StoreManager& StoreMgr = Eng.getStateManager().getStoreManager();
   StoreManager::InvalidatedSymbols IS;
-  Store store = state->getStore();
 
   // NOTE: Even if RegionsToInvalidate is empty, we must still invalidate
   //  global variables.
-  store = StoreMgr.InvalidateRegions(store, RegionsToInvalidate.data(),
-                                     RegionsToInvalidate.data() +
-                                     RegionsToInvalidate.size(),
-                                     Ex, Count, &IS,
-                                     /* invalidateGlobals = */ true);
+  state = state->InvalidateRegions(RegionsToInvalidate.data(),
+                                   RegionsToInvalidate.data() +
+                                   RegionsToInvalidate.size(),
+                                   Ex, Count, &IS,
+                                   /* invalidateGlobals = */ true);
 
-  state = state->makeWithStore(store);
   for (StoreManager::InvalidatedSymbols::iterator I = IS.begin(),
        E = IS.end(); I!=E; ++I) {
-      // Remove any existing reference-count binding.
+    SymbolRef sym = *I;
+    if (WhitelistedSymbols.count(sym))
+      continue;
+    // Remove any existing reference-count binding.
     state = state->remove<RefBindings>(*I);
   }
 
@@ -2860,7 +2759,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst,
 void CFRefCount::EvalCall(ExplodedNodeSet& Dst,
                           GRExprEngine& Eng,
                           GRStmtNodeBuilder& Builder,
-                          CallExpr* CE, SVal L,
+                          const CallExpr* CE, SVal L,
                           ExplodedNode* Pred) {
 
   RetainSummary *Summ = 0;
@@ -2874,7 +2773,7 @@ void CFRefCount::EvalCall(ExplodedNodeSet& Dst,
   else {
     const FunctionDecl* FD = L.getAsFunctionDecl();
     Summ = !FD ? Summaries.getDefaultSummary() :
-                 Summaries.getSummary(const_cast<FunctionDecl*>(FD));
+                 Summaries.getSummary(FD);
   }
 
   assert(Summ);
@@ -2885,7 +2784,7 @@ void CFRefCount::EvalCall(ExplodedNodeSet& Dst,
 void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet& Dst,
                                      GRExprEngine& Eng,
                                      GRStmtNodeBuilder& Builder,
-                                     ObjCMessageExpr* ME,
+                                     const ObjCMessageExpr* ME,
                                      ExplodedNode* Pred,
                                      const GRState *state) {
   RetainSummary *Summ =
@@ -2956,10 +2855,10 @@ void CFRefCount::EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) {
 void CFRefCount::EvalReturn(ExplodedNodeSet& Dst,
                             GRExprEngine& Eng,
                             GRStmtNodeBuilder& Builder,
-                            ReturnStmt* S,
+                            const ReturnStmt* S,
                             ExplodedNode* Pred) {
 
-  Expr* RetE = S->getRetValue();
+  const Expr* RetE = S->getRetValue();
   if (!RetE)
     return;
 
@@ -3404,7 +3303,7 @@ void CFRefCount::EvalDeadSymbols(ExplodedNodeSet& Dst,
                                  ExplodedNode* Pred,
                                  const GRState* state,
                                  SymbolReaper& SymReaper) {
-  Stmt *S = Builder.getStmt();
+  const Stmt *S = Builder.getStmt();
   RefBindings B = state->get<RefBindings>();
 
   // Update counts from autorelease pools
@@ -3454,7 +3353,8 @@ void CFRefCount::EvalDeadSymbols(ExplodedNodeSet& Dst,
 
 void CFRefCount::ProcessNonLeakError(ExplodedNodeSet& Dst,
                                      GRStmtNodeBuilder& Builder,
-                                     Expr* NodeExpr, SourceRange ErrorRange,
+                                     const Expr* NodeExpr, 
+                                     SourceRange ErrorRange,
                                      ExplodedNode* Pred,
                                      const GRState* St,
                                      RefVal::Kind hasErr, SymbolRef Sym) {
diff --git a/lib/Checker/CMakeLists.txt b/lib/Checker/CMakeLists.txt
index 259346a..5b54f0d 100644
--- a/lib/Checker/CMakeLists.txt
+++ b/lib/Checker/CMakeLists.txt
@@ -4,6 +4,7 @@ add_clang_library(clangChecker
   AdjustedReturnValueChecker.cpp
   AggExprVisitor.cpp
   AnalysisConsumer.cpp
+  AnalysisManager.cpp
   ArrayBoundChecker.cpp
   AttrNonNullChecker.cpp
   BasicConstraintManager.cpp
@@ -15,7 +16,6 @@ add_clang_library(clangChecker
   BuiltinFunctionChecker.cpp
   CFRefCount.cpp
   CallAndMessageChecker.cpp
-  CallInliner.cpp
   CastSizeChecker.cpp
   CastToStructChecker.cpp
   CheckDeadStores.cpp
@@ -24,6 +24,7 @@ add_clang_library(clangChecker
   CheckSecuritySyntaxOnly.cpp
   CheckSizeofPointer.cpp
   Checker.cpp
+  CheckerHelpers.cpp
   CocoaConventions.cpp
   CStringChecker.cpp
   DereferenceChecker.cpp
@@ -74,6 +75,7 @@ add_clang_library(clangChecker
   UndefinedArraySubscriptChecker.cpp
   UndefinedAssignmentChecker.cpp
   UnixAPIChecker.cpp
+  UnreachableCodeChecker.cpp
   VLASizeChecker.cpp
   ValueManager.cpp
   )
diff --git a/lib/Checker/CStringChecker.cpp b/lib/Checker/CStringChecker.cpp
index a92d409..9ea572f 100644
--- a/lib/Checker/CStringChecker.cpp
+++ b/lib/Checker/CStringChecker.cpp
@@ -15,19 +15,30 @@
 #include "GRExprEngineExperimentalChecks.h"
 #include "clang/Checker/BugReporter/BugType.h"
 #include "clang/Checker/PathSensitive/CheckerVisitor.h"
+#include "clang/Checker/PathSensitive/GRStateTrait.h"
 #include "llvm/ADT/StringSwitch.h"
 
 using namespace clang;
 
 namespace {
 class CStringChecker : public CheckerVisitor<CStringChecker> {
-  BugType *BT_Null, *BT_Bounds, *BT_Overlap;
+  BugType *BT_Null, *BT_Bounds, *BT_BoundsWrite, *BT_Overlap, *BT_NotCString;
 public:
   CStringChecker()
-  : BT_Null(0), BT_Bounds(0), BT_Overlap(0) {}
+  : BT_Null(0), BT_Bounds(0), BT_BoundsWrite(0), BT_Overlap(0), BT_NotCString(0)
+  {}
   static void *getTag() { static int tag; return &tag; }
 
   bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
+  void PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS);
+  void MarkLiveSymbols(const GRState *state, SymbolReaper &SR);
+  void EvalDeadSymbols(CheckerContext &C, SymbolReaper &SR);
+  bool WantsRegionChangeUpdate(const GRState *state);
+
+  const GRState *EvalRegionChanges(const GRState *state,
+                                   const MemRegion * const *Begin,
+                                   const MemRegion * const *End,
+                                   bool*);
 
   typedef void (CStringChecker::*FnCheck)(CheckerContext &, const CallExpr *);
 
@@ -40,26 +51,61 @@ public:
 
   void EvalMemcmp(CheckerContext &C, const CallExpr *CE);
 
+  void EvalStrlen(CheckerContext &C, const CallExpr *CE);
+
+  void EvalStrcpy(CheckerContext &C, const CallExpr *CE);
+  void EvalStpcpy(CheckerContext &C, const CallExpr *CE);
+  void EvalStrcpyCommon(CheckerContext &C, const CallExpr *CE, bool ReturnEnd);
+
   // Utility methods
   std::pair<const GRState*, const GRState*>
   AssumeZero(CheckerContext &C, const GRState *state, SVal V, QualType Ty);
 
+  const GRState *SetCStringLength(const GRState *state, const MemRegion *MR,
+                                  SVal StrLen);
+  SVal GetCStringLengthForRegion(CheckerContext &C, const GRState *&state,
+                                 const Expr *Ex, const MemRegion *MR);
+  SVal GetCStringLength(CheckerContext &C, const GRState *&state,
+                        const Expr *Ex, SVal Buf);
+
+  const GRState *InvalidateBuffer(CheckerContext &C, const GRState *state,
+                                  const Expr *Ex, SVal V);
+
+  bool SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx,
+                       const MemRegion *MR);
+
+  // Re-usable checks
   const GRState *CheckNonNull(CheckerContext &C, const GRState *state,
                                const Expr *S, SVal l);
   const GRState *CheckLocation(CheckerContext &C, const GRState *state,
-                               const Expr *S, SVal l);
+                               const Expr *S, SVal l,
+                               bool IsDestination = false);
   const GRState *CheckBufferAccess(CheckerContext &C, const GRState *state,
                                    const Expr *Size,
                                    const Expr *FirstBuf,
-                                   const Expr *SecondBuf = NULL);
+                                   const Expr *SecondBuf = NULL,
+                                   bool FirstIsDestination = false);
   const GRState *CheckOverlap(CheckerContext &C, const GRState *state,
                               const Expr *Size, const Expr *First,
                               const Expr *Second);
   void EmitOverlapBug(CheckerContext &C, const GRState *state,
                       const Stmt *First, const Stmt *Second);
 };
+
+class CStringLength {
+public:
+  typedef llvm::ImmutableMap<const MemRegion *, SVal> EntryMap;
+};
 } //end anonymous namespace
 
+namespace clang {
+  template <>
+  struct GRStateTrait<CStringLength> 
+    : public GRStatePartialTrait<CStringLength::EntryMap> {
+    static void *GDMIndex() { return CStringChecker::getTag(); }
+  };
+}
+
 void clang::RegisterCStringChecker(GRExprEngine &Eng) {
   Eng.registerCheck(new CStringChecker());
 }
@@ -122,7 +168,8 @@ const GRState *CStringChecker::CheckNonNull(CheckerContext &C,
 // FIXME: This was originally copied from ArrayBoundChecker.cpp. Refactor?
 const GRState *CStringChecker::CheckLocation(CheckerContext &C,
                                              const GRState *state,
-                                             const Expr *S, SVal l) {
+                                             const Expr *S, SVal l,
+                                             bool IsDestination) {
   // If a previous check has failed, propagate the failure.
   if (!state)
     return NULL;
@@ -136,7 +183,7 @@ const GRState *CStringChecker::CheckLocation(CheckerContext &C,
   if (!ER)
     return state;
 
-  assert(ER->getValueType(C.getASTContext()) == C.getASTContext().CharTy &&
+  assert(ER->getValueType() == C.getASTContext().CharTy &&
     "CheckLocation should only be called with char* ElementRegions");
 
   // Get the size of the array.
@@ -155,17 +202,26 @@ const GRState *CStringChecker::CheckLocation(CheckerContext &C,
     if (!N)
       return NULL;
 
-    if (!BT_Bounds)
-      BT_Bounds = new BuiltinBug("Out-of-bound array access",
-        "Byte string function accesses out-of-bound array element "
-        "(buffer overflow)");
+    BuiltinBug *BT;
+    if (IsDestination) {
+      if (!BT_BoundsWrite) {
+        BT_BoundsWrite = new BuiltinBug("Out-of-bound array access",
+          "Byte string function overflows destination buffer");
+      }
+      BT = static_cast<BuiltinBug*>(BT_BoundsWrite);
+    } else {
+      if (!BT_Bounds) {
+        BT_Bounds = new BuiltinBug("Out-of-bound array access",
+          "Byte string function accesses out-of-bound array element");
+      }
+      BT = static_cast<BuiltinBug*>(BT_Bounds);
+    }
 
     // FIXME: It would be nice to eventually make this diagnostic more clear,
     // e.g., by referencing the original declaration or by saying *why* this
     // reference is outside the range.
 
     // Generate a report for this bug.
-    BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Bounds);
     RangedBugReport *report = new RangedBugReport(*BT, BT->getDescription(), N);
 
     report->addRange(S->getSourceRange());
@@ -182,7 +238,8 @@ const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C,
                                                  const GRState *state,
                                                  const Expr *Size,
                                                  const Expr *FirstBuf,
-                                                 const Expr *SecondBuf) {
+                                                 const Expr *SecondBuf,
+                                                 bool FirstIsDestination) {
   // If a previous check has failed, propagate the failure.
   if (!state)
     return NULL;
@@ -191,7 +248,7 @@ const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C,
   SValuator &SV = VM.getSValuator();
   ASTContext &Ctx = C.getASTContext();
 
-  QualType SizeTy = Ctx.getSizeType();
+  QualType SizeTy = Size->getType();
   QualType PtrTy = Ctx.getPointerType(Ctx.CharTy);
 
   // Check that the first buffer is non-null.
@@ -208,18 +265,20 @@ const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C,
 
   // Compute the offset of the last element to be accessed: size-1.
   NonLoc One = cast<NonLoc>(VM.makeIntVal(1, SizeTy));
-  NonLoc LastOffset = cast<NonLoc>(SV.EvalBinOpNN(state, BinaryOperator::Sub,
+  NonLoc LastOffset = cast<NonLoc>(SV.EvalBinOpNN(state, BO_Sub,
                                                   *Length, One, SizeTy));
 
   // Check that the first buffer is sufficently long.
-  Loc BufStart = cast<Loc>(SV.EvalCast(BufVal, PtrTy, FirstBuf->getType()));
-  SVal BufEnd
-    = SV.EvalBinOpLN(state, BinaryOperator::Add, BufStart, LastOffset, PtrTy);
-  state = CheckLocation(C, state, FirstBuf, BufEnd);
+  SVal BufStart = SV.EvalCast(BufVal, PtrTy, FirstBuf->getType());
+  if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) {
+    SVal BufEnd = SV.EvalBinOpLN(state, BO_Add, *BufLoc,
+                                 LastOffset, PtrTy);
+    state = CheckLocation(C, state, FirstBuf, BufEnd, FirstIsDestination);
 
-  // If the buffer isn't large enough, abort.
-  if (!state)
-    return NULL;
+    // If the buffer isn't large enough, abort.
+    if (!state)
+      return NULL;
+  }
 
   // If there's a second buffer, check it as well.
   if (SecondBuf) {
@@ -228,10 +287,12 @@ const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C,
     if (!state)
       return NULL;
 
-    BufStart = cast<Loc>(SV.EvalCast(BufVal, PtrTy, SecondBuf->getType()));
-    BufEnd
-      = SV.EvalBinOpLN(state, BinaryOperator::Add, BufStart, LastOffset, PtrTy);
-    state = CheckLocation(C, state, SecondBuf, BufEnd);
+    BufStart = SV.EvalCast(BufVal, PtrTy, SecondBuf->getType());
+    if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) {
+      SVal BufEnd = SV.EvalBinOpLN(state, BO_Add, *BufLoc,
+                                   LastOffset, PtrTy);
+      state = CheckLocation(C, state, SecondBuf, BufEnd);
+    }
   }
 
   // Large enough or not, return this state!
@@ -284,7 +345,7 @@ const GRState *CStringChecker::CheckOverlap(CheckerContext &C,
 
   // Which value comes first?
   QualType CmpTy = Ctx.IntTy;
-  SVal Reverse = SV.EvalBinOpLL(state, BinaryOperator::GT,
+  SVal Reverse = SV.EvalBinOpLL(state, BO_GT,
                                 *FirstLoc, *SecondLoc, CmpTy);
   DefinedOrUnknownSVal *ReverseTest = dyn_cast<DefinedOrUnknownSVal>(&Reverse);
   if (!ReverseTest)
@@ -324,14 +385,14 @@ const GRState *CStringChecker::CheckOverlap(CheckerContext &C,
     return state;
 
   // Compute the end of the first buffer. Bail out if THAT fails.
-  SVal FirstEnd = SV.EvalBinOpLN(state, BinaryOperator::Add,
+  SVal FirstEnd = SV.EvalBinOpLN(state, BO_Add,
                                  *FirstStartLoc, *Length, CharPtrTy);
   Loc *FirstEndLoc = dyn_cast<Loc>(&FirstEnd);
   if (!FirstEndLoc)
     return state;
 
   // Is the end of the first buffer past the start of the second buffer?
-  SVal Overlap = SV.EvalBinOpLL(state, BinaryOperator::GT,
+  SVal Overlap = SV.EvalBinOpLL(state, BO_GT,
                                 *FirstEndLoc, *SecondLoc, CmpTy);
   DefinedOrUnknownSVal *OverlapTest = dyn_cast<DefinedOrUnknownSVal>(&Overlap);
   if (!OverlapTest)
@@ -369,6 +430,222 @@ void CStringChecker::EmitOverlapBug(CheckerContext &C, const GRState *state,
   C.EmitReport(report);
 }
 
+const GRState *CStringChecker::SetCStringLength(const GRState *state,
+                                                const MemRegion *MR,
+                                                SVal StrLen) {
+  assert(!StrLen.isUndef() && "Attempt to set an undefined string length");
+  if (StrLen.isUnknown())
+    return state;
+
+  MR = MR->StripCasts();
+
+  switch (MR->getKind()) {
+  case MemRegion::StringRegionKind:
+    // FIXME: This can happen if we strcpy() into a string region. This is
+    // undefined [C99 6.4.5p6], but we should still warn about it.
+    return state;
+
+  case MemRegion::SymbolicRegionKind:
+  case MemRegion::AllocaRegionKind:
+  case MemRegion::VarRegionKind:
+  case MemRegion::FieldRegionKind:
+  case MemRegion::ObjCIvarRegionKind:
+    return state->set<CStringLength>(MR, StrLen);
+
+  case MemRegion::ElementRegionKind:
+    // FIXME: Handle element regions by upper-bounding the parent region's
+    // string length.
+    return state;
+
+  default:
+    // Other regions (mostly non-data) can't have a reliable C string length.
+    // For now, just ignore the change.
+    // FIXME: These are rare but not impossible. We should output some kind of
+    // warning for things like strcpy((char[]){'a', 0}, "b");
+    return state;
+  }
+}
+
+SVal CStringChecker::GetCStringLengthForRegion(CheckerContext &C,
+                                               const GRState *&state,
+                                               const Expr *Ex,
+                                               const MemRegion *MR) {
+  // If there's a recorded length, go ahead and return it.
+  const SVal *Recorded = state->get<CStringLength>(MR);
+  if (Recorded)
+    return *Recorded;
+  
+  // Otherwise, get a new symbol and update the state.
+  unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
+  ValueManager &ValMgr = C.getValueManager();
+  QualType SizeTy = ValMgr.getContext().getSizeType();
+  SVal Strlen = ValMgr.getMetadataSymbolVal(getTag(), MR, Ex, SizeTy, Count);
+  
+  state = state->set<CStringLength>(MR, Strlen);
+  return Strlen;
+}
+
+SVal CStringChecker::GetCStringLength(CheckerContext &C, const GRState *&state,
+                                      const Expr *Ex, SVal Buf) {
+  const MemRegion *MR = Buf.getAsRegion();
+  if (!MR) {
+    // If we can't get a region, see if it's something we /know/ isn't a
+    // C string. In the context of locations, the only time we can issue such
+    // a warning is for labels.
+    if (loc::GotoLabel *Label = dyn_cast<loc::GotoLabel>(&Buf)) {
+      if (ExplodedNode *N = C.GenerateNode(state)) {
+        if (!BT_NotCString)
+          BT_NotCString = new BuiltinBug("API",
+            "Argument is not a null-terminated string.");
+
+        llvm::SmallString<120> buf;
+        llvm::raw_svector_ostream os(buf);
+        os << "Argument to byte string function is the address of the label '"
+           << Label->getLabel()->getID()->getName()
+           << "', which is not a null-terminated string";
+
+        // Generate a report for this bug.
+        EnhancedBugReport *report = new EnhancedBugReport(*BT_NotCString,
+                                                          os.str(), N);
+
+        report->addRange(Ex->getSourceRange());
+        C.EmitReport(report);        
+      }
+
+      return UndefinedVal();
+    }
+
+    // If it's not a region and not a label, give up.
+    return UnknownVal();
+  }
+
+  // If we have a region, strip casts from it and see if we can figure out
+  // its length. For anything we can't figure out, just return UnknownVal.
+  MR = MR->StripCasts();
+
+  switch (MR->getKind()) {
+  case MemRegion::StringRegionKind: {
+    // Modifying the contents of string regions is undefined [C99 6.4.5p6],
+    // so we can assume that the byte length is the correct C string length.
+    ValueManager &ValMgr = C.getValueManager();
+    QualType SizeTy = ValMgr.getContext().getSizeType();
+    const StringLiteral *Str = cast<StringRegion>(MR)->getStringLiteral();
+    return ValMgr.makeIntVal(Str->getByteLength(), SizeTy);
+  }
+  case MemRegion::SymbolicRegionKind:
+  case MemRegion::AllocaRegionKind:
+  case MemRegion::VarRegionKind:
+  case MemRegion::FieldRegionKind:
+  case MemRegion::ObjCIvarRegionKind:
+    return GetCStringLengthForRegion(C, state, Ex, MR);
+  case MemRegion::CompoundLiteralRegionKind:
+    // FIXME: Can we track this? Is it necessary?
+    return UnknownVal();
+  case MemRegion::ElementRegionKind:
+    // FIXME: How can we handle this? It's not good enough to subtract the
+    // offset from the base string length; consider "123\x00567" and &a[5].
+    return UnknownVal();
+  default:
+    // Other regions (mostly non-data) can't have a reliable C string length.
+    // In this case, an error is emitted and UndefinedVal is returned.
+    // The caller should always be prepared to handle this case.
+    if (ExplodedNode *N = C.GenerateNode(state)) {
+      if (!BT_NotCString)
+        BT_NotCString = new BuiltinBug("API",
+          "Argument is not a null-terminated string.");
+
+      llvm::SmallString<120> buf;
+      llvm::raw_svector_ostream os(buf);
+
+      os << "Argument to byte string function is ";
+
+      if (SummarizeRegion(os, C.getASTContext(), MR))
+        os << ", which is not a null-terminated string";
+      else
+        os << "not a null-terminated string";
+
+      // Generate a report for this bug.
+      EnhancedBugReport *report = new EnhancedBugReport(*BT_NotCString,
+                                                        os.str(), N);
+
+      report->addRange(Ex->getSourceRange());
+      C.EmitReport(report);        
+    }
+
+    return UndefinedVal();
+  }
+}
+
+const GRState *CStringChecker::InvalidateBuffer(CheckerContext &C,
+                                                const GRState *state,
+                                                const Expr *E, SVal V) {
+  Loc *L = dyn_cast<Loc>(&V);
+  if (!L)
+    return state;
+
+  // FIXME: This is a simplified version of what's in CFRefCount.cpp -- it makes
+  // some assumptions about the value that CFRefCount can't. Even so, it should
+  // probably be refactored.
+  if (loc::MemRegionVal* MR = dyn_cast<loc::MemRegionVal>(L)) {
+    const MemRegion *R = MR->getRegion()->StripCasts();
+
+    // Are we dealing with an ElementRegion?  If so, we should be invalidating
+    // the super-region.
+    if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
+      R = ER->getSuperRegion();
+      // FIXME: What about layers of ElementRegions?
+    }
+
+    // Invalidate this region.
+    unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
+    return state->InvalidateRegion(R, E, Count, NULL);
+  }
+
+  // If we have a non-region value by chance, just remove the binding.
+  // FIXME: is this necessary or correct? This handles the non-Region
+  //  cases.  Is it ever valid to store to these?
+  return state->unbindLoc(*L);
+}
+
+bool CStringChecker::SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx,
+                                     const MemRegion *MR) {
+  const TypedRegion *TR = dyn_cast<TypedRegion>(MR);
+  if (!TR)
+    return false;
+
+  switch (TR->getKind()) {
+  case MemRegion::FunctionTextRegionKind: {
+    const FunctionDecl *FD = cast<FunctionTextRegion>(TR)->getDecl();
+    if (FD)
+      os << "the address of the function '" << FD << "'";
+    else
+      os << "the address of a function";
+    return true;
+  }
+  case MemRegion::BlockTextRegionKind:
+    os << "block text";
+    return true;
+  case MemRegion::BlockDataRegionKind:
+    os << "a block";
+    return true;
+  case MemRegion::CXXThisRegionKind:
+  case MemRegion::CXXObjectRegionKind:
+    os << "a C++ object of type " << TR->getValueType().getAsString();
+    return true;
+  case MemRegion::VarRegionKind:
+    os << "a variable of type" << TR->getValueType().getAsString();
+    return true;
+  case MemRegion::FieldRegionKind:
+    os << "a field of type " << TR->getValueType().getAsString();
+    return true;
+  case MemRegion::ObjCIvarRegionKind:
+    os << "an instance variable of type " << TR->getValueType().getAsString();
+    return true;
+  default:
+    return false;
+  }
+}
+
 //===----------------------------------------------------------------------===//
 // Evaluation of individual function calls.
 //===----------------------------------------------------------------------===//
@@ -390,11 +667,20 @@ void CStringChecker::EvalCopyCommon(CheckerContext &C, const GRState *state,
   // If the size can be nonzero, we have to check the other arguments.
   if (StNonZeroSize) {
     state = StNonZeroSize;
-    state = CheckBufferAccess(C, state, Size, Dest, Source);
+    state = CheckBufferAccess(C, state, Size, Dest, Source,
+                              /* FirstIsDst = */ true);
     if (Restricted)
       state = CheckOverlap(C, state, Size, Dest, Source);
-    if (state)
+
+    if (state) {
+      // Invalidate the destination.
+      // FIXME: Even if we can't perfectly model the copy, we should see if we
+      // can use LazyCompoundVals to copy the source values into the destination.
+      // This would probably remove any existing bindings past the end of the
+      // copied region, but that's still an improvement over blank invalidation.
+      state = InvalidateBuffer(C, state, Dest, state->getSVal(Dest));
       C.addTransition(state);
+    }
   }
 }
 
@@ -481,7 +767,7 @@ void CStringChecker::EvalMemcmp(CheckerContext &C, const CallExpr *CE) {
       if (state) {
         // The return value is the comparison result, which we don't know.
         unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
-        SVal CmpV = ValMgr.getConjuredSymbolVal(NULL, CE, CE->getType(), Count);
+        SVal CmpV = ValMgr.getConjuredSymbolVal(NULL, CE, Count);
         state = state->BindExpr(CE, CmpV);
         C.addTransition(state);
       }
@@ -489,8 +775,123 @@ void CStringChecker::EvalMemcmp(CheckerContext &C, const CallExpr *CE) {
   }
 }
 
+void CStringChecker::EvalStrlen(CheckerContext &C, const CallExpr *CE) {
+  // size_t strlen(const char *s);
+  const GRState *state = C.getState();
+  const Expr *Arg = CE->getArg(0);
+  SVal ArgVal = state->getSVal(Arg);
+
+  // Check that the argument is non-null.
+  state = CheckNonNull(C, state, Arg, ArgVal);
+
+  if (state) {
+    SVal StrLen = GetCStringLength(C, state, Arg, ArgVal);
+
+    // If the argument isn't a valid C string, there's no valid state to
+    // transition to.
+    if (StrLen.isUndef())
+      return;
+
+    // If GetCStringLength couldn't figure out the length, conjure a return
+    // value, so it can be used in constraints, at least.
+    if (StrLen.isUnknown()) {
+      ValueManager &ValMgr = C.getValueManager();
+      unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
+      StrLen = ValMgr.getConjuredSymbolVal(NULL, CE, Count);
+    }
+
+    // Bind the return value.
+    state = state->BindExpr(CE, StrLen);
+    C.addTransition(state);
+  }
+}
+
+void CStringChecker::EvalStrcpy(CheckerContext &C, const CallExpr *CE) {
+  // char *strcpy(char *restrict dst, const char *restrict src);
+  EvalStrcpyCommon(C, CE, /* ReturnEnd = */ false);
+}
+
+void CStringChecker::EvalStpcpy(CheckerContext &C, const CallExpr *CE) {
+  // char *stpcpy(char *restrict dst, const char *restrict src);
+  EvalStrcpyCommon(C, CE, /* ReturnEnd = */ true);
+}
+
+void CStringChecker::EvalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
+                                      bool ReturnEnd) {
+  const GRState *state = C.getState();
+
+  // Check that the destination is non-null
+  const Expr *Dst = CE->getArg(0);
+  SVal DstVal = state->getSVal(Dst);
+
+  state = CheckNonNull(C, state, Dst, DstVal);
+  if (!state)
+    return;
+
+  // Check that the source is non-null.
+  const Expr *Src = CE->getArg(1);
+  SVal SrcVal = state->getSVal(Src);
+
+  state = CheckNonNull(C, state, Src, SrcVal);
+  if (!state)
+    return;
+
+  // Get the string length of the source.
+  SVal StrLen = GetCStringLength(C, state, Src, SrcVal);
+
+  // If the source isn't a valid C string, give up.
+  if (StrLen.isUndef())
+    return;
+
+  SVal Result = (ReturnEnd ? UnknownVal() : DstVal);
+
+  // If the destination is a MemRegion, try to check for a buffer overflow and
+  // record the new string length.
+  if (loc::MemRegionVal *DstRegVal = dyn_cast<loc::MemRegionVal>(&DstVal)) {
+    // If the length is known, we can check for an overflow.
+    if (NonLoc *KnownStrLen = dyn_cast<NonLoc>(&StrLen)) {
+      SValuator &SV = C.getSValuator();
+
+      SVal LastElement = SV.EvalBinOpLN(state, BO_Add,
+                                        *DstRegVal, *KnownStrLen,
+                                        Dst->getType());
+
+      state = CheckLocation(C, state, Dst, LastElement, /* IsDst = */ true);
+      if (!state)
+        return;
+
+      // If this is a stpcpy-style copy, the last element is the return value.
+      if (ReturnEnd)
+        Result = LastElement;
+    }
+
+    // Invalidate the destination. This must happen before we set the C string
+    // length because invalidation will clear the length.
+    // FIXME: Even if we can't perfectly model the copy, we should see if we
+    // can use LazyCompoundVals to copy the source values into the destination.
+    // This would probably remove any existing bindings past the end of the
+    // string, but that's still an improvement over blank invalidation.
+    state = InvalidateBuffer(C, state, Dst, *DstRegVal);
+
+    // Set the C string length of the destination.
+    state = SetCStringLength(state, DstRegVal->getRegion(), StrLen);
+  }
+
+  // If this is a stpcpy-style copy, but we were unable to check for a buffer
+  // overflow, we still need a result. Conjure a return value.
+  if (ReturnEnd && Result.isUnknown()) {
+    ValueManager &ValMgr = C.getValueManager();
+    unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
+    StrLen = ValMgr.getConjuredSymbolVal(NULL, CE, Count);
+  }
+
+  // Set the return value.
+  state = state->BindExpr(CE, Result);
+  C.addTransition(state);
+}
+
 //===----------------------------------------------------------------------===//
-// The driver method.
+// The driver method, and other Checker callbacks.
 //===----------------------------------------------------------------------===//
 
 bool CStringChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
@@ -512,6 +913,9 @@ bool CStringChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
     .Cases("memcpy", "__memcpy_chk", &CStringChecker::EvalMemcpy)
     .Cases("memcmp", "bcmp", &CStringChecker::EvalMemcmp)
     .Cases("memmove", "__memmove_chk", &CStringChecker::EvalMemmove)
+    .Cases("strcpy", "__strcpy_chk", &CStringChecker::EvalStrcpy)
+    .Cases("stpcpy", "__stpcpy_chk", &CStringChecker::EvalStpcpy)
+    .Case("strlen", &CStringChecker::EvalStrlen)
     .Case("bcopy", &CStringChecker::EvalBcopy)
     .Default(NULL);
 
@@ -523,3 +927,129 @@ bool CStringChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
   (this->*EvalFunction)(C, CE);
   return true;
 }
+
+void CStringChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) {
+  // Record string length for char a[] = "abc";
+  const GRState *state = C.getState();
+
+  for (DeclStmt::const_decl_iterator I = DS->decl_begin(), E = DS->decl_end();
+       I != E; ++I) {
+    const VarDecl *D = dyn_cast<VarDecl>(*I);
+    if (!D)
+      continue;
+
+    // FIXME: Handle array fields of structs.
+    if (!D->getType()->isArrayType())
+      continue;
+
+    const Expr *Init = D->getInit();
+    if (!Init)
+      continue;
+    if (!isa<StringLiteral>(Init))
+      continue;
+
+    Loc VarLoc = state->getLValue(D, C.getPredecessor()->getLocationContext());
+    const MemRegion *MR = VarLoc.getAsRegion();
+    if (!MR)
+      continue;
+
+    SVal StrVal = state->getSVal(Init);
+    assert(StrVal.isValid() && "Initializer string is unknown or undefined");
+    DefinedOrUnknownSVal StrLen
+      = cast<DefinedOrUnknownSVal>(GetCStringLength(C, state, Init, StrVal));
+
+    state = state->set<CStringLength>(MR, StrLen);
+  }
+
+  C.addTransition(state);
+}
+
+bool CStringChecker::WantsRegionChangeUpdate(const GRState *state) {
+  CStringLength::EntryMap Entries = state->get<CStringLength>();
+  return !Entries.isEmpty();
+}
+
+const GRState *CStringChecker::EvalRegionChanges(const GRState *state,
+                                                 const MemRegion * const *Begin,
+                                                 const MemRegion * const *End,
+                                                 bool *) {
+  CStringLength::EntryMap Entries = state->get<CStringLength>();
+  if (Entries.isEmpty())
+    return state;
+
+  llvm::SmallPtrSet<const MemRegion *, 8> Invalidated;
+  llvm::SmallPtrSet<const MemRegion *, 32> SuperRegions;
+
+  // First build sets for the changed regions and their super-regions.
+  for ( ; Begin != End; ++Begin) {
+    const MemRegion *MR = *Begin;
+    Invalidated.insert(MR);
+
+    SuperRegions.insert(MR);
+    while (const SubRegion *SR = dyn_cast<SubRegion>(MR)) {
+      MR = SR->getSuperRegion();
+      SuperRegions.insert(MR);
+    }
+  }
+
+  CStringLength::EntryMap::Factory &F = state->get_context<CStringLength>();
+
+  // Then loop over the entries in the current state.
+  for (CStringLength::EntryMap::iterator I = Entries.begin(),
+       E = Entries.end(); I != E; ++I) {
+    const MemRegion *MR = I.getKey();
+
+    // Is this entry for a super-region of a changed region?
+    if (SuperRegions.count(MR)) {
+      Entries = F.Remove(Entries, MR);
+      continue;
+    }
+
+    // Is this entry for a sub-region of a changed region?
+    const MemRegion *Super = MR;
+    while (const SubRegion *SR = dyn_cast<SubRegion>(Super)) {
+      Super = SR->getSuperRegion();
+      if (Invalidated.count(Super)) {
+        Entries = F.Remove(Entries, MR);
+        break;
+      }
+    }
+  }
+
+  return state->set<CStringLength>(Entries);
+}
+
+void CStringChecker::MarkLiveSymbols(const GRState *state, SymbolReaper &SR) {
+  // Mark all symbols in our string length map as valid.
+  CStringLength::EntryMap Entries = state->get<CStringLength>();
+
+  for (CStringLength::EntryMap::iterator I = Entries.begin(), E = Entries.end();
+       I != E; ++I) {
+    SVal Len = I.getData();
+    if (SymbolRef Sym = Len.getAsSymbol())
+      SR.markInUse(Sym);
+  }
+}
+
+void CStringChecker::EvalDeadSymbols(CheckerContext &C, SymbolReaper &SR) {
+  if (!SR.hasDeadSymbols())
+    return;
+
+  const GRState *state = C.getState();
+  CStringLength::EntryMap Entries = state->get<CStringLength>();
+  if (Entries.isEmpty())
+    return;
+
+  CStringLength::EntryMap::Factory &F = state->get_context<CStringLength>();
+  for (CStringLength::EntryMap::iterator I = Entries.begin(), E = Entries.end();
+       I != E; ++I) {
+    SVal Len = I.getData();
+    if (SymbolRef Sym = Len.getAsSymbol()) {
+      if (SR.isDead(Sym))
+        Entries = F.Remove(Entries, I.getKey());
+    }
+  }
+
+  state = state->set<CStringLength>(Entries);
+  C.GenerateNode(state);
+}
diff --git a/lib/Checker/CallAndMessageChecker.cpp b/lib/Checker/CallAndMessageChecker.cpp
index c619d75..3c9ddce 100644
--- a/lib/Checker/CallAndMessageChecker.cpp
+++ b/lib/Checker/CallAndMessageChecker.cpp
@@ -114,7 +114,7 @@ bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
       : C(c), StoreMgr(storeMgr), MrMgr(mrMgr), store(s) {}
 
       bool Find(const TypedRegion *R) {
-        QualType T = R->getValueType(C);
+        QualType T = R->getValueType();
         if (const RecordType *RT = T->getAsStructureType()) {
           const RecordDecl *RD = RT->getDecl()->getDefinition();
           assert(RD && "Referred record has no definition");
diff --git a/lib/Checker/CallInliner.cpp b/lib/Checker/CallInliner.cpp
deleted file mode 100644
index c47e06c..0000000
--- a/lib/Checker/CallInliner.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-//===--- CallInliner.cpp - Transfer function that inlines callee ----------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-//  This file implements the callee inlining transfer function.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Checker/PathSensitive/CheckerVisitor.h"
-#include "clang/Checker/PathSensitive/GRState.h"
-#include "clang/Checker/Checkers/LocalCheckers.h"
-
-using namespace clang;
-
-namespace {
-class CallInliner : public Checker {
-public:
-  static void *getTag() {
-    static int x;
-    return &x;
-  }
-
-  virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
-};
-}
-
-void clang::RegisterCallInliner(GRExprEngine &Eng) {
-  Eng.registerCheck(new CallInliner());
-}
-
-bool CallInliner::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
-  const GRState *state = C.getState();
-  const Expr *Callee = CE->getCallee();
-  SVal L = state->getSVal(Callee);
-  
-  const FunctionDecl *FD = L.getAsFunctionDecl();
-  if (!FD)
-    return false;
-
-  if (!FD->hasBody(FD))
-    return false;
-
-  // Now we have the definition of the callee, create a CallEnter node.
-  CallEnter Loc(CE, FD, C.getPredecessor()->getLocationContext());
-  C.addTransition(state, Loc);
-
-  return true;
-}
-
diff --git a/lib/Checker/CastSizeChecker.cpp b/lib/Checker/CastSizeChecker.cpp
index a502c10..6676fe5 100644
--- a/lib/Checker/CastSizeChecker.cpp
+++ b/lib/Checker/CastSizeChecker.cpp
@@ -44,6 +44,10 @@ void CastSizeChecker::PreVisitCastExpr(CheckerContext &C, const CastExpr *CE) {
 
   QualType ToPointeeTy = ToPTy->getPointeeType();
 
+  // Only perform the check if 'ToPointeeTy' is a complete type.
+  if (ToPointeeTy->isIncompleteType())
+    return;
+
   const GRState *state = C.getState();
   const MemRegion *R = state->getSVal(E).getAsRegion();
   if (R == 0)
diff --git a/lib/Checker/CheckDeadStores.cpp b/lib/Checker/CheckDeadStores.cpp
index d6ea187..3896100 100644
--- a/lib/Checker/CheckDeadStores.cpp
+++ b/lib/Checker/CheckDeadStores.cpp
@@ -217,7 +217,7 @@ public:
               // If x is EVER assigned a new value later, don't issue
               // a warning.  This is because such initialization can be
               // due to defensive programming.
-              if (E->isConstantInitializer(Ctx))
+              if (E->isConstantInitializer(Ctx, false))
                 return;
 
               if (DeclRefExpr *DRE=dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
@@ -268,7 +268,7 @@ public:
     // Check for '&'.  Any VarDecl whose value has its address-taken we
     // treat as escaped.
     Expr* E = U->getSubExpr()->IgnoreParenCasts();
-    if (U->getOpcode() == UnaryOperator::AddrOf)
+    if (U->getOpcode() == UO_AddrOf)
       if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E))
         if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) {
           Escaped.insert(VD);
diff --git a/lib/Checker/CheckSecuritySyntaxOnly.cpp b/lib/Checker/CheckSecuritySyntaxOnly.cpp
index af85c2f..9a2ac45 100644
--- a/lib/Checker/CheckSecuritySyntaxOnly.cpp
+++ b/lib/Checker/CheckSecuritySyntaxOnly.cpp
@@ -41,8 +41,8 @@ class WalkAST : public StmtVisitor<WalkAST> {
 
 public:
   WalkAST(BugReporter &br) : BR(br),
-			     II_gets(0), II_getpw(0), II_mktemp(0),
-			     II_rand(), II_random(0), II_setid(),
+                             II_gets(0), II_getpw(0), II_mktemp(0),
+                             II_rand(), II_random(0), II_setid(),
                  CheckRand(isArc4RandomAvailable(BR.getContext())) {}
 
   // Statement visitor methods.
@@ -131,7 +131,7 @@ GetIncrementedVar(const Expr *expr, const VarDecl *x, const VarDecl *y) {
 
   if (const BinaryOperator *B = dyn_cast<BinaryOperator>(expr)) {
     if (!(B->isAssignmentOp() || B->isCompoundAssignmentOp() ||
-          B->getOpcode() == BinaryOperator::Comma))
+          B->getOpcode() == BO_Comma))
       return NULL;
 
     if (const DeclRefExpr *lhs = GetIncrementedVar(B->getLHS(), x, y))
@@ -217,7 +217,7 @@ void WalkAST::CheckLoopConditionForFloat(const ForStmt *FS) {
   llvm::SmallString<256> sbuf;
   llvm::raw_svector_ostream os(sbuf);
 
-  os << "Variable '" << drCond->getDecl()->getNameAsCString()
+  os << "Variable '" << drCond->getDecl()->getName()
      << "' with floating point type '" << drCond->getType().getAsString()
      << "' should not be used as a loop counter";
 
@@ -332,10 +332,10 @@ void WalkAST::CheckCall_mktemp(const CallExpr *CE, const FunctionDecl *FD) {
   // Issue a waring.
   SourceRange R = CE->getCallee()->getSourceRange();
   BR.EmitBasicReport("Potential insecure temporary file in call 'mktemp'",
-		     "Security",
-		     "Call to function 'mktemp' is insecure as it always "
-		     "creates or uses insecure temporary file.  Use 'mkstemp' instead",
-		     CE->getLocStart(), &R, 1);
+                     "Security",
+                     "Call to function 'mktemp' is insecure as it always "
+                     "creates or uses insecure temporary file.  Use 'mkstemp' instead",
+                     CE->getLocStart(), &R, 1);
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/lib/Checker/CheckerHelpers.cpp b/lib/Checker/CheckerHelpers.cpp
new file mode 100644
index 0000000..ece6943
--- /dev/null
+++ b/lib/Checker/CheckerHelpers.cpp
@@ -0,0 +1,80 @@
+//===---- CheckerHelpers.cpp - Helper functions for checkers ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines several static functions for use in checkers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Checker/PathSensitive/CheckerHelpers.h"
+#include "clang/AST/Expr.h"
+
+// Recursively find any substatements containing macros
+bool clang::containsMacro(const Stmt *S) {
+  if (S->getLocStart().isMacroID())
+    return true;
+
+  if (S->getLocEnd().isMacroID())
+    return true;
+
+  for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
+      ++I)
+    if (const Stmt *child = *I)
+      if (containsMacro(child))
+        return true;
+
+  return false;
+}
+
+// Recursively find any substatements containing enum constants
+bool clang::containsEnum(const Stmt *S) {
+  const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S);
+
+  if (DR && isa<EnumConstantDecl>(DR->getDecl()))
+    return true;
+
+  for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
+      ++I)
+    if (const Stmt *child = *I)
+      if (containsEnum(child))
+        return true;
+
+  return false;
+}
+
+// Recursively find any substatements containing static vars
+bool clang::containsStaticLocal(const Stmt *S) {
+  const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S);
+
+  if (DR)
+    if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
+      if (VD->isStaticLocal())
+        return true;
+
+  for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
+      ++I)
+    if (const Stmt *child = *I)
+      if (containsStaticLocal(child))
+        return true;
+
+  return false;
+}
+
+// Recursively find any substatements containing __builtin_offsetof
+bool clang::containsBuiltinOffsetOf(const Stmt *S) {
+  if (isa<OffsetOfExpr>(S))
+    return true;
+
+  for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
+      ++I)
+    if (const Stmt *child = *I)
+      if (containsBuiltinOffsetOf(child))
+        return true;
+
+  return false;
+}
diff --git a/lib/Checker/CocoaConventions.cpp b/lib/Checker/CocoaConventions.cpp
index 3ba887c..b446a04 100644
--- a/lib/Checker/CocoaConventions.cpp
+++ b/lib/Checker/CocoaConventions.cpp
@@ -173,9 +173,10 @@ bool cocoa::isCocoaObjectRef(QualType Ty) {
   if (!PT)
     return true;
   
-  // We assume that id<..>, id, and "Class" all represent tracked objects.
+  // We assume that id<..>, id, Class, and Class<..> all represent tracked
+  // objects.
   if (PT->isObjCIdType() || PT->isObjCQualifiedIdType() ||
-      PT->isObjCClassType())
+      PT->isObjCClassType() || PT->isObjCQualifiedClassType())
     return true;
   
   // Does the interface subclass NSObject?
diff --git a/lib/Checker/DivZeroChecker.cpp b/lib/Checker/DivZeroChecker.cpp
index e09a871..32e2a17 100644
--- a/lib/Checker/DivZeroChecker.cpp
+++ b/lib/Checker/DivZeroChecker.cpp
@@ -40,10 +40,10 @@ void *DivZeroChecker::getTag() {
 void DivZeroChecker::PreVisitBinaryOperator(CheckerContext &C,
                                             const BinaryOperator *B) {
   BinaryOperator::Opcode Op = B->getOpcode();
-  if (Op != BinaryOperator::Div &&
-      Op != BinaryOperator::Rem &&
-      Op != BinaryOperator::DivAssign &&
-      Op != BinaryOperator::RemAssign)
+  if (Op != BO_Div &&
+      Op != BO_Rem &&
+      Op != BO_DivAssign &&
+      Op != BO_RemAssign)
     return;
 
   if (!B->getRHS()->getType()->isIntegerType() ||
diff --git a/lib/Checker/Environment.cpp b/lib/Checker/Environment.cpp
index 48152ce..02291f4 100644
--- a/lib/Checker/Environment.cpp
+++ b/lib/Checker/Environment.cpp
@@ -80,7 +80,7 @@ SVal Environment::GetSVal(const Stmt *E, ValueManager& ValMgr) const {
   return LookupExpr(E);
 }
 
-Environment EnvironmentManager::BindExpr(Environment Env, const Stmt *S,
+Environment EnvironmentManager::bindExpr(Environment Env, const Stmt *S,
                                          SVal V, bool Invalidate) {
   assert(S);
 
@@ -94,6 +94,16 @@ Environment EnvironmentManager::BindExpr(Environment Env, const Stmt *S,
   return Environment(F.Add(Env.ExprBindings, S, V));
 }
 
+static inline const Stmt *MakeLocation(const Stmt *S) {
+  return (const Stmt*) (((uintptr_t) S) | 0x1);
+}
+
+Environment EnvironmentManager::bindExprAndLocation(Environment Env,
+                                                    const Stmt *S,
+                                                    SVal location, SVal V) {
+  return Environment(F.Add(F.Add(Env.ExprBindings, MakeLocation(S), V), S, V));
+}
+
 namespace {
 class MarkLiveCallback : public SymbolVisitor {
   SymbolReaper &SymReaper;
@@ -115,6 +125,12 @@ static bool isBlockExprInCallers(const Stmt *E, const LocationContext *LC) {
   return false;
 }
 
+// In addition to mapping from Stmt * - > SVals in the Environment, we also
+// maintain a mapping from Stmt * -> SVals (locations) that were used during
+// a load and store.
+static inline bool IsLocation(const Stmt *S) {
+  return (bool) (((uintptr_t) S) & 0x1);
+}
 
 // RemoveDeadBindings:
 //  - Remove subexpression bindings.
@@ -123,7 +139,6 @@ static bool isBlockExprInCallers(const Stmt *E, const LocationContext *LC) {
 //   - Mark their reachable symbols live in SymbolReaper,
 //     see ScanReachableSymbols.
 //   - Mark the region in DRoots if the binding is a loc::MemRegionVal.
-
 Environment
 EnvironmentManager::RemoveDeadBindings(Environment Env,
                                        SymbolReaper &SymReaper,
@@ -136,12 +151,25 @@ EnvironmentManager::RemoveDeadBindings(Environment Env,
   // individually removing all the subexpression bindings (which will greatly
   // outnumber block-level expression bindings).
   Environment NewEnv = getInitialEnvironment();
+  
+  llvm::SmallVector<std::pair<const Stmt*, SVal>, 10> deferredLocations;
 
   // Iterate over the block-expr bindings.
   for (Environment::iterator I = Env.begin(), E = Env.end();
        I != E; ++I) {
 
     const Stmt *BlkExpr = I.getKey();
+    
+    // For recorded locations (used when evaluating loads and stores), we
+    // consider them live only when their associated normal expression is
+    // also live.
+    // NOTE: This assumes that loads/stores that evaluated to UnknownVal
+    // still have an entry in the map.
+    if (IsLocation(BlkExpr)) {
+      deferredLocations.push_back(std::make_pair(BlkExpr, I.getData()));
+      continue;
+    }
+    
     const SVal &X = I.getData();
 
     // Block-level expressions in callers are assumed always live.
@@ -186,6 +214,15 @@ EnvironmentManager::RemoveDeadBindings(Environment Env,
     if (X.isUndef() && cast<UndefinedVal>(X).getData())
       NewEnv.ExprBindings = F.Add(NewEnv.ExprBindings, BlkExpr, X);
   }
+  
+  // Go through he deferred locations and add them to the new environment if
+  // the correspond Stmt* is in the map as well.
+  for (llvm::SmallVectorImpl<std::pair<const Stmt*, SVal> >::iterator
+      I = deferredLocations.begin(), E = deferredLocations.end(); I != E; ++I) {
+    const Stmt *S = (Stmt*) (((uintptr_t) I->first) & (uintptr_t) ~0x1);
+    if (NewEnv.ExprBindings.lookup(S))
+      NewEnv.ExprBindings = F.Add(NewEnv.ExprBindings, I->first, I->second);
+  }
 
   return NewEnv;
 }
diff --git a/lib/Checker/FixedAddressChecker.cpp b/lib/Checker/FixedAddressChecker.cpp
index 4fce45b..29a3c3a 100644
--- a/lib/Checker/FixedAddressChecker.cpp
+++ b/lib/Checker/FixedAddressChecker.cpp
@@ -40,7 +40,7 @@ void FixedAddressChecker::PreVisitBinaryOperator(CheckerContext &C,
   // Using a fixed address is not portable because that address will probably
   // not be valid in all environments or platforms.
 
-  if (B->getOpcode() != BinaryOperator::Assign)
+  if (B->getOpcode() != BO_Assign)
     return;
 
   QualType T = B->getType();
diff --git a/lib/Checker/FlatStore.cpp b/lib/Checker/FlatStore.cpp
index 64575b3c9..21fa422 100644
--- a/lib/Checker/FlatStore.cpp
+++ b/lib/Checker/FlatStore.cpp
@@ -44,11 +44,10 @@ public:
   }
 
   SVal ArrayToPointer(Loc Array);
-  const GRState *RemoveDeadBindings(GRState &state, 
-                           const StackFrameContext *LCtx,
+  Store RemoveDeadBindings(Store store, const StackFrameContext *LCtx,
                            SymbolReaper& SymReaper,
                          llvm::SmallVectorImpl<const MemRegion*>& RegionRoots){
-    return StateMgr.getPersistentState(state);
+    return store;
   }
 
   Store BindDecl(Store store, const VarRegion *VR, SVal initVal);
@@ -57,13 +56,10 @@ public:
 
   typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols;
   
-  Store InvalidateRegion(Store store, const MemRegion *R, const Expr *E, 
-                         unsigned Count, InvalidatedSymbols *IS);
-  
   Store InvalidateRegions(Store store, const MemRegion * const *I,
                           const MemRegion * const *E, const Expr *Ex,
                           unsigned Count, InvalidatedSymbols *IS,
-                          bool invalidateGlobals);
+                          bool invalidateGlobals, InvalidatedRegions *Regions);
 
   void print(Store store, llvm::raw_ostream& Out, const char* nl, 
              const char *sep);
@@ -74,7 +70,14 @@ private:
     return RegionBindings(static_cast<const RegionBindings::TreeTy*>(store));
   }
 
-  Interval RegionToInterval(const MemRegion *R);
+  class RegionInterval {
+  public:
+    const MemRegion *R;
+    Interval I;
+    RegionInterval(const MemRegion *r, int64_t s, int64_t e) : R(r), I(s, e){}
+  };
+
+  RegionInterval RegionToInterval(const MemRegion *R);
 
   SVal RetrieveRegionWithNoBinding(const MemRegion *R, QualType T);
 };
@@ -86,11 +89,15 @@ StoreManager *clang::CreateFlatStoreManager(GRStateManager &StMgr) {
 
 SVal FlatStoreManager::Retrieve(Store store, Loc L, QualType T) {
   const MemRegion *R = cast<loc::MemRegionVal>(L).getRegion();
-  Interval I = RegionToInterval(R);
+  RegionInterval RI = RegionToInterval(R);
+  // FIXME: FlatStore should handle regions with unknown intervals.
+  if (!RI.R)
+    return UnknownVal();
+
   RegionBindings B = getRegionBindings(store);
-  const BindingVal *BV = B.lookup(R);
+  const BindingVal *BV = B.lookup(RI.R);
   if (BV) {
-    const SVal *V = BVFactory.Lookup(*BV, I);
+    const SVal *V = BVFactory.Lookup(*BV, RI.I);
     if (V)
       return *V;
     else
@@ -116,9 +123,12 @@ Store FlatStoreManager::Bind(Store store, Loc L, SVal val) {
   if (V)
     BV = *V;
 
-  Interval I = RegionToInterval(R);
-  BV = BVFactory.Add(BV, I, val);
-  B = RBFactory.Add(B, R, BV);
+  RegionInterval RI = RegionToInterval(R);
+  // FIXME: FlatStore should handle regions with unknown intervals.
+  if (!RI.R)
+    return B.getRoot();
+  BV = BVFactory.Add(BV, RI.I, val);
+  B = RBFactory.Add(B, RI.R, BV);
   return B.getRoot();
 }
 
@@ -139,7 +149,7 @@ SVal FlatStoreManager::ArrayToPointer(Loc Array) {
 
 Store FlatStoreManager::BindDecl(Store store, const VarRegion *VR, 
                                  SVal initVal) {
-  return store;
+  return Bind(store, ValMgr.makeLoc(VR), initVal);
 }
 
 Store FlatStoreManager::BindDeclWithNoInit(Store store, const VarRegion *VR) {
@@ -147,18 +157,12 @@ Store FlatStoreManager::BindDeclWithNoInit(Store store, const VarRegion *VR) {
 }
 
 Store FlatStoreManager::InvalidateRegions(Store store,
-                                            const MemRegion * const *I,
-                                            const MemRegion * const *E,
-                                            const Expr *Ex, unsigned Count,
-                                            InvalidatedSymbols *IS,
-                                            bool invalidateGlobals) {
-  assert(false && "Not implemented");
-  return store;
-}
-
-Store FlatStoreManager::InvalidateRegion(Store store, const MemRegion *R,
-                                         const Expr *E, unsigned Count,
-                                         InvalidatedSymbols *IS) {
+                                          const MemRegion * const *I,
+                                          const MemRegion * const *E,
+                                          const Expr *Ex, unsigned Count,
+                                          InvalidatedSymbols *IS,
+                                          bool invalidateGlobals,
+                                          InvalidatedRegions *Regions) {
   assert(false && "Not implemented");
   return store;
 }
@@ -170,15 +174,29 @@ void FlatStoreManager::print(Store store, llvm::raw_ostream& Out,
 void FlatStoreManager::iterBindings(Store store, BindingsHandler& f) {
 }
 
-Interval FlatStoreManager::RegionToInterval(const MemRegion *R) { 
+FlatStoreManager::RegionInterval 
+FlatStoreManager::RegionToInterval(const MemRegion *R) { 
   switch (R->getKind()) {
   case MemRegion::VarRegionKind: {
-    QualType T = cast<VarRegion>(R)->getValueType(Ctx);
-    uint64_t Size = Ctx.getTypeSize(T);
-    return Interval(0, Size-1);
+    QualType T = cast<VarRegion>(R)->getValueType();
+    int64_t Size = Ctx.getTypeSize(T);
+    return RegionInterval(R, 0, Size-1);
   }
+
+  case MemRegion::ElementRegionKind: 
+  case MemRegion::FieldRegionKind: {
+    RegionOffset Offset = R->getAsOffset();
+    // We cannot compute offset for all regions, for example, elements
+    // with symbolic offsets.
+    if (!Offset.getRegion())
+      return RegionInterval(0, 0, 0);
+    int64_t Start = Offset.getOffset();
+    int64_t Size = Ctx.getTypeSize(cast<TypedRegion>(R)->getValueType());
+    return RegionInterval(Offset.getRegion(), Start, Start+Size);
+  }
+
   default:
     llvm_unreachable("Region kind unhandled.");
-    return Interval(0, 0);
+    return RegionInterval(0, 0, 0);
   }
 }
diff --git a/lib/Checker/GRCXXExprEngine.cpp b/lib/Checker/GRCXXExprEngine.cpp
index 18e112c..a49989b 100644
--- a/lib/Checker/GRCXXExprEngine.cpp
+++ b/lib/Checker/GRCXXExprEngine.cpp
@@ -17,7 +17,7 @@
 
 using namespace clang;
 
-void GRExprEngine::EvalArguments(ExprIterator AI, ExprIterator AE,
+void GRExprEngine::EvalArguments(ConstExprIterator AI, ConstExprIterator AE,
                                  const FunctionProtoType *FnType, 
                                  ExplodedNode *Pred, ExplodedNodeSet &Dst) {
   llvm::SmallVector<CallExprWLItem, 20> WorkList;
@@ -55,7 +55,7 @@ const CXXThisRegion *GRExprEngine::getCXXThisRegion(const CXXMethodDecl *D,
   return ValMgr.getRegionManager().getCXXThisRegion(PT, SFC);
 }
 
-void GRExprEngine::CreateCXXTemporaryObject(Expr *Ex, ExplodedNode *Pred,
+void GRExprEngine::CreateCXXTemporaryObject(const Expr *Ex, ExplodedNode *Pred,
                                             ExplodedNodeSet &Dst) {
   ExplodedNodeSet Tmp;
   Visit(Ex, Pred, Tmp);
@@ -94,9 +94,7 @@ void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest,
   // Evaluate other arguments.
   ExplodedNodeSet ArgsEvaluated;
   const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>();
-  EvalArguments(const_cast<CXXConstructExpr*>(E)->arg_begin(),
-                const_cast<CXXConstructExpr*>(E)->arg_end(),
-                FnType, Pred, ArgsEvaluated);
+  EvalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, ArgsEvaluated);
   // The callee stack frame context used to create the 'this' parameter region.
   const StackFrameContext *SFC = AMgr.getStackFrame(CD, 
                                                     Pred->getLocationContext(),
@@ -104,11 +102,12 @@ void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest,
 
   const CXXThisRegion *ThisR = getCXXThisRegion(E->getConstructor(), SFC);
 
-  CallEnter Loc(E, CD, Pred->getLocationContext());
+  CallEnter Loc(E, SFC->getAnalysisContext(), Pred->getLocationContext());
   for (ExplodedNodeSet::iterator NI = ArgsEvaluated.begin(),
                                  NE = ArgsEvaluated.end(); NI != NE; ++NI) {
     const GRState *state = GetState(*NI);
-    // Setup 'this' region.
+    // Setup 'this' region, so that the ctor is evaluated on the object pointed
+    // by 'Dest'.
     state = state->bindLoc(loc::MemRegionVal(ThisR), Dest);
     ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
     if (N)
@@ -126,9 +125,7 @@ void GRExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE,
 
   // Evaluate explicit arguments with a worklist.
   ExplodedNodeSet ArgsEvaluated;
-  EvalArguments(const_cast<CXXMemberCallExpr*>(MCE)->arg_begin(),
-                const_cast<CXXMemberCallExpr*>(MCE)->arg_end(),
-                FnType, Pred, ArgsEvaluated);
+  EvalArguments(MCE->arg_begin(), MCE->arg_end(), FnType, Pred, ArgsEvaluated);
  
   // Evaluate the implicit object argument.
   ExplodedNodeSet AllArgsEvaluated;
@@ -157,7 +154,7 @@ void GRExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE,
                                                     Builder->getBlock(), 
                                                     Builder->getIndex());
   const CXXThisRegion *ThisR = getCXXThisRegion(MD, SFC);
-  CallEnter Loc(MCE, MD, Pred->getLocationContext());
+  CallEnter Loc(MCE, SFC->getAnalysisContext(), Pred->getLocationContext());
   for (ExplodedNodeSet::iterator I = AllArgsEvaluated.begin(),
          E = AllArgsEvaluated.end(); I != E; ++I) {
     // Set up 'this' region.
@@ -169,7 +166,7 @@ void GRExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE,
   }
 }
 
-void GRExprEngine::VisitCXXNewExpr(CXXNewExpr *CNE, ExplodedNode *Pred,
+void GRExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
                                    ExplodedNodeSet &Dst) {
   if (CNE->isArray()) {
     // FIXME: allocating an array has not been handled.
@@ -177,7 +174,7 @@ void GRExprEngine::VisitCXXNewExpr(CXXNewExpr *CNE, ExplodedNode *Pred,
   }
 
   unsigned Count = Builder->getCurrentBlockCount();
-  DefinedOrUnknownSVal SymVal = getValueManager().getConjuredSymbolVal(NULL,CNE, 
+  DefinedOrUnknownSVal SymVal = getValueManager().getConjuredSymbolVal(NULL,CNE,
                                                          CNE->getType(), Count);
   const MemRegion *NewReg = cast<loc::MemRegionVal>(SymVal).getRegion();
 
@@ -201,10 +198,7 @@ void GRExprEngine::VisitCXXNewExpr(CXXNewExpr *CNE, ExplodedNode *Pred,
     const GRState *state = GetState(*I);
 
     if (ObjTy->isRecordType()) {
-      Store store = state->getStore();
-      StoreManager::InvalidatedSymbols IS;
-      store = getStoreManager().InvalidateRegion(store, EleReg, CNE, Count, &IS);
-      state = state->makeWithStore(store);
+      state = state->InvalidateRegion(EleReg, CNE, Count);
     } else {
       if (CNE->hasInitializer()) {
         SVal V = state->getSVal(*CNE->constructor_arg_begin());
@@ -220,8 +214,8 @@ void GRExprEngine::VisitCXXNewExpr(CXXNewExpr *CNE, ExplodedNode *Pred,
   }
 }
 
-void GRExprEngine::VisitCXXDeleteExpr(CXXDeleteExpr *CDE, ExplodedNode *Pred,
-                                      ExplodedNodeSet &Dst) {
+void GRExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, 
+                                      ExplodedNode *Pred,ExplodedNodeSet &Dst) {
   // Should do more checking.
   ExplodedNodeSet ArgEvaluated;
   Visit(CDE->getArgument(), Pred, ArgEvaluated);
@@ -232,7 +226,7 @@ void GRExprEngine::VisitCXXDeleteExpr(CXXDeleteExpr *CDE, ExplodedNode *Pred,
   }
 }
 
-void GRExprEngine::VisitCXXThisExpr(CXXThisExpr *TE, ExplodedNode *Pred,
+void GRExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
                                     ExplodedNodeSet &Dst) {
   // Get the this object region from StoreManager.
   const MemRegion *R =
diff --git a/lib/Checker/GRCoreEngine.cpp b/lib/Checker/GRCoreEngine.cpp
index a816186..5125f36 100644
--- a/lib/Checker/GRCoreEngine.cpp
+++ b/lib/Checker/GRCoreEngine.cpp
@@ -12,8 +12,10 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "clang/Checker/PathSensitive/AnalysisManager.h"
 #include "clang/Checker/PathSensitive/GRCoreEngine.h"
 #include "clang/Checker/PathSensitive/GRExprEngine.h"
+#include "clang/Index/TranslationUnit.h"
 #include "clang/AST/Expr.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/ADT/DenseMap.h"
@@ -24,6 +26,12 @@ using llvm::cast;
 using llvm::isa;
 using namespace clang;
 
+// This should be removed in the future.
+namespace clang {
+GRTransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
+                                  const LangOptions& lopts);
+}
+
 //===----------------------------------------------------------------------===//
 // Worklist classes for exploration of reachable states.
 //===----------------------------------------------------------------------===//
@@ -118,47 +126,15 @@ GRWorkList* GRWorkList::MakeBFSBlockDFSContents() {
 //===----------------------------------------------------------------------===//
 // Core analysis engine.
 //===----------------------------------------------------------------------===//
-void GRCoreEngine::ProcessEndPath(GREndPathNodeBuilder& Builder) {
-  SubEngine.ProcessEndPath(Builder);
-}
-
-void GRCoreEngine::ProcessStmt(CFGElement E, GRStmtNodeBuilder& Builder) {
-  SubEngine.ProcessStmt(E, Builder);
-}
-
-bool GRCoreEngine::ProcessBlockEntrance(CFGBlock* Blk, const ExplodedNode *Pred,
-                                        GRBlockCounter BC) {
-  return SubEngine.ProcessBlockEntrance(Blk, Pred, BC);
-}
-
-void GRCoreEngine::ProcessBranch(Stmt* Condition, Stmt* Terminator,
-                   GRBranchNodeBuilder& Builder) {
-  SubEngine.ProcessBranch(Condition, Terminator, Builder);
-}
-
-void GRCoreEngine::ProcessIndirectGoto(GRIndirectGotoNodeBuilder& Builder) {
-  SubEngine.ProcessIndirectGoto(Builder);
-}
-
-void GRCoreEngine::ProcessSwitch(GRSwitchNodeBuilder& Builder) {
-  SubEngine.ProcessSwitch(Builder);
-}
-
-void GRCoreEngine::ProcessCallEnter(GRCallEnterNodeBuilder &Builder) {
-  SubEngine.ProcessCallEnter(Builder);
-}
-
-void GRCoreEngine::ProcessCallExit(GRCallExitNodeBuilder &Builder) {
-  SubEngine.ProcessCallExit(Builder);
-}
 
 /// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
-bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps) {
+bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps,
+                                   const GRState *InitState) {
 
   if (G->num_roots() == 0) { // Initialize the analysis by constructing
     // the root if none exists.
 
-    CFGBlock* Entry = &(L->getCFG()->getEntry());
+    const CFGBlock* Entry = &(L->getCFG()->getEntry());
 
     assert (Entry->empty() &&
             "Entry block must be empty.");
@@ -167,7 +143,7 @@ bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps) {
             "Entry block must have 1 successor.");
 
     // Get the solitary successor.
-    CFGBlock* Succ = *(Entry->succ_begin());
+    const CFGBlock* Succ = *(Entry->succ_begin());
 
     // Construct an edge representing the
     // starting location in the function.
@@ -176,8 +152,11 @@ bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps) {
     // Set the current block counter to being empty.
     WList->setBlockCounter(BCounterFactory.GetEmptyCounter());
 
-    // Generate the root.
-    GenerateNode(StartLoc, getInitialState(L), 0);
+    if (!InitState)
+      // Generate the root.
+      GenerateNode(StartLoc, getInitialState(L), 0);
+    else
+      GenerateNode(StartLoc, InitState, 0);
   }
 
   while (Steps && WList->hasWork()) {
@@ -221,14 +200,25 @@ bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps) {
     }
   }
 
-  SubEngine.ProcessEndWorklist(WList->hasWork() || BlockAborted);
+  SubEngine.ProcessEndWorklist(hasWorkRemaining());
   return WList->hasWork();
 }
 
+void GRCoreEngine::ExecuteWorkListWithInitialState(const LocationContext *L, 
+                                                   unsigned Steps,
+                                                   const GRState *InitState, 
+                                                   ExplodedNodeSet &Dst) {
+  ExecuteWorkList(L, Steps, InitState);
+  for (llvm::SmallVectorImpl<ExplodedNode*>::iterator I = G->EndNodes.begin(), 
+                                           E = G->EndNodes.end(); I != E; ++I) {
+    Dst.Add(*I);
+  }
+}
+
 void GRCoreEngine::HandleCallEnter(const CallEnter &L, const CFGBlock *Block,
                                    unsigned Index, ExplodedNode *Pred) {
-  GRCallEnterNodeBuilder Builder(*this, Pred, L.getCallExpr(), L.getCallee(), 
-                                 Block, Index);
+  GRCallEnterNodeBuilder Builder(*this, Pred, L.getCallExpr(), 
+                                 L.getCalleeContext(), Block, Index);
   ProcessCallEnter(Builder);
 }
 
@@ -239,7 +229,7 @@ void GRCoreEngine::HandleCallExit(const CallExit &L, ExplodedNode *Pred) {
 
 void GRCoreEngine::HandleBlockEdge(const BlockEdge& L, ExplodedNode* Pred) {
 
-  CFGBlock* Blk = L.getDst();
+  const CFGBlock* Blk = L.getDst();
 
   // Check if we are entering the EXIT block.
   if (Blk == &(L.getLocationContext()->getCFG()->getExit())) {
@@ -260,8 +250,9 @@ void GRCoreEngine::HandleBlockEdge(const BlockEdge& L, ExplodedNode* Pred) {
   if (ProcessBlockEntrance(Blk, Pred, WList->getBlockCounter()))
     GenerateNode(BlockEntrance(Blk, Pred->getLocationContext()),
                  Pred->State, Pred);
-  else
-    BlockAborted = true;
+  else {
+    blocksAborted.push_back(std::make_pair(L, Pred));
+  }
 }
 
 void GRCoreEngine::HandleBlockEntrance(const BlockEntrance& L,
@@ -284,9 +275,9 @@ void GRCoreEngine::HandleBlockEntrance(const BlockEntrance& L,
     HandleBlockExit(L.getBlock(), Pred);
 }
 
-void GRCoreEngine::HandleBlockExit(CFGBlock * B, ExplodedNode* Pred) {
+void GRCoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode* Pred) {
 
-  if (Stmt* Term = B->getTerminator()) {
+  if (const Stmt* Term = B->getTerminator()) {
     switch (Term->getStmtClass()) {
       default:
         assert(false && "Analysis for this terminator not implemented.");
@@ -372,8 +363,8 @@ void GRCoreEngine::HandleBlockExit(CFGBlock * B, ExplodedNode* Pred) {
                Pred->State, Pred);
 }
 
-void GRCoreEngine::HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock * B,
-                                ExplodedNode* Pred) {
+void GRCoreEngine::HandleBranch(const Stmt* Cond, const Stmt* Term, 
+                                const CFGBlock * B, ExplodedNode* Pred) {
   assert (B->succ_size() == 2);
 
   GRBranchNodeBuilder Builder(B, *(B->succ_begin()), *(B->succ_begin()+1),
@@ -382,7 +373,7 @@ void GRCoreEngine::HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock * B,
   ProcessBranch(Cond, Term, Builder);
 }
 
-void GRCoreEngine::HandlePostStmt(const PostStmt& L, CFGBlock* B,
+void GRCoreEngine::HandlePostStmt(const PostStmt& L, const CFGBlock* B,
                                   unsigned StmtIdx, ExplodedNode* Pred) {
 
   assert (!B->empty());
@@ -415,7 +406,7 @@ void GRCoreEngine::GenerateNode(const ProgramPoint& Loc,
   if (IsNew) WList->Enqueue(Node);
 }
 
-GRStmtNodeBuilder::GRStmtNodeBuilder(CFGBlock* b, unsigned idx,
+GRStmtNodeBuilder::GRStmtNodeBuilder(const CFGBlock* b, unsigned idx,
                                      ExplodedNode* N, GRCoreEngine* e,
                                      GRStateManager &mgr)
   : Eng(*e), B(*b), Idx(idx), Pred(N), Mgr(mgr), Auditor(0),
@@ -438,7 +429,7 @@ void GRStmtNodeBuilder::GenerateAutoTransition(ExplodedNode* N) {
   if (isa<CallEnter>(N->getLocation())) {
     // Still use the index of the CallExpr. It's needed to create the callee
     // StackFrameContext.
-    Eng.WList->Enqueue(N, B, Idx);
+    Eng.WList->Enqueue(N, &B, Idx);
     return;
   }
 
@@ -447,7 +438,7 @@ void GRStmtNodeBuilder::GenerateAutoTransition(ExplodedNode* N) {
   if (Loc == N->getLocation()) {
     // Note: 'N' should be a fresh node because otherwise it shouldn't be
     // a member of Deferred.
-    Eng.WList->Enqueue(N, B, Idx+1);
+    Eng.WList->Enqueue(N, &B, Idx+1);
     return;
   }
 
@@ -456,10 +447,10 @@ void GRStmtNodeBuilder::GenerateAutoTransition(ExplodedNode* N) {
   Succ->addPredecessor(N, *Eng.G);
 
   if (IsNew)
-    Eng.WList->Enqueue(Succ, B, Idx+1);
+    Eng.WList->Enqueue(Succ, &B, Idx+1);
 }
 
-ExplodedNode* GRStmtNodeBuilder::MakeNode(ExplodedNodeSet& Dst, Stmt* S, 
+ExplodedNode* GRStmtNodeBuilder::MakeNode(ExplodedNodeSet& Dst, const Stmt* S, 
                                           ExplodedNode* Pred, const GRState* St,
                                           ProgramPoint::Kind K) {
   const GRState* PredState = GetState(Pred);
@@ -692,6 +683,59 @@ void GREndPathNodeBuilder::GenerateCallExitNode(const GRState *state) {
 
 void GRCallEnterNodeBuilder::GenerateNode(const GRState *state,
                                           const LocationContext *LocCtx) {
+  // Check if the callee is in the same translation unit.
+  if (CalleeCtx->getTranslationUnit() != 
+      Pred->getLocationContext()->getTranslationUnit()) {
+    // Create a new engine. We must be careful that the new engine should not
+    // reference data structures owned by the old engine.
+
+    AnalysisManager &OldMgr = Eng.SubEngine.getAnalysisManager();
+    
+    // Get the callee's translation unit.
+    idx::TranslationUnit *TU = CalleeCtx->getTranslationUnit();
+
+    // Create a new AnalysisManager with components of the callee's
+    // TranslationUnit.
+    // The Diagnostic is actually shared when we create ASTUnits from AST files.
+    AnalysisManager AMgr(TU->getASTContext(), TU->getDiagnostic(), 
+                         OldMgr.getLangOptions(), 
+                         OldMgr.getPathDiagnosticClient(),
+                         OldMgr.getStoreManagerCreator(),
+                         OldMgr.getConstraintManagerCreator(),
+                         OldMgr.getIndexer(),
+                         OldMgr.getMaxNodes(), OldMgr.getMaxLoop(),
+                         OldMgr.shouldVisualizeGraphviz(),
+                         OldMgr.shouldVisualizeUbigraph(),
+                         OldMgr.shouldPurgeDead(),
+                         OldMgr.shouldEagerlyAssume(),
+                         OldMgr.shouldTrimGraph(),
+                         OldMgr.shouldInlineCall(),
+                     OldMgr.getAnalysisContextManager().getUseUnoptimizedCFG());
+    llvm::OwningPtr<GRTransferFuncs> TF(MakeCFRefCountTF(AMgr.getASTContext(),
+                                                         /* GCEnabled */ false,
+                                                        AMgr.getLangOptions()));
+    // Create the new engine.
+    GRExprEngine NewEng(AMgr, TF.take());
+
+    // Create the new LocationContext.
+    AnalysisContext *NewAnaCtx = AMgr.getAnalysisContext(CalleeCtx->getDecl(), 
+                                               CalleeCtx->getTranslationUnit());
+    const StackFrameContext *OldLocCtx = cast<StackFrameContext>(LocCtx);
+    const StackFrameContext *NewLocCtx = AMgr.getStackFrame(NewAnaCtx, 
+                                               OldLocCtx->getParent(),
+                                               OldLocCtx->getCallSite(),
+                                               OldLocCtx->getCallSiteBlock(), 
+                                               OldLocCtx->getIndex());
+
+    // Now create an initial state for the new engine.
+    const GRState *NewState = NewEng.getStateManager().MarshalState(state,
+                                                                    NewLocCtx);
+    ExplodedNodeSet ReturnNodes;
+    NewEng.ExecuteWorkListWithInitialState(NewLocCtx, AMgr.getMaxNodes(), 
+                                           NewState, ReturnNodes);
+    return;
+  }
+
   // Get the callee entry block.
   const CFGBlock *Entry = &(LocCtx->getCFG()->getEntry());
   assert(Entry->empty());
@@ -721,6 +765,6 @@ void GRCallExitNodeBuilder::GenerateNode(const GRState *state) {
   ExplodedNode *Node = Eng.G->getNode(Loc, state, &isNew);
   Node->addPredecessor(const_cast<ExplodedNode*>(Pred), *Eng.G);
   if (isNew)
-    Eng.WList->Enqueue(Node, *const_cast<CFGBlock*>(LocCtx->getCallSiteBlock()),
+    Eng.WList->Enqueue(Node, LocCtx->getCallSiteBlock(),
                        LocCtx->getIndex() + 1);
 }
diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp
index 07fee9d..feb826e 100644
--- a/lib/Checker/GRExprEngine.cpp
+++ b/lib/Checker/GRExprEngine.cpp
@@ -169,17 +169,18 @@ public:
 // Checker worklist routines.
 //===----------------------------------------------------------------------===//
 
-void GRExprEngine::CheckerVisit(Stmt *S, ExplodedNodeSet &Dst,
-                                ExplodedNodeSet &Src, bool isPrevisit) {
+void GRExprEngine::CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst,
+                                ExplodedNodeSet &Src, CallbackKind Kind) {
 
   // Determine if we already have a cached 'CheckersOrdered' vector
-  // specifically tailored for the provided <Stmt kind, isPrevisit>.  This
+  // specifically tailored for the provided <CallbackKind, Stmt kind>.  This
   // can reduce the number of checkers actually called.
   CheckersOrdered *CO = &Checkers;
   llvm::OwningPtr<CheckersOrdered> NewCO;
-  
-  const std::pair<unsigned, unsigned> &K =
-    std::make_pair((unsigned)S->getStmtClass(), isPrevisit ? 1U : 0U);
+
+  // The cache key is made up of the and the callback kind (pre- or post-visit)
+  // and the statement kind.
+  CallbackTag K = GetCallbackTag(Kind, S->getStmtClass());
 
   CheckersOrdered *& CO_Ref = COCache[K];
   
@@ -204,7 +205,10 @@ void GRExprEngine::CheckerVisit(Stmt *S, ExplodedNodeSet &Dst,
   ExplodedNodeSet *PrevSet = &Src;
   unsigned checkersEvaluated = 0;
 
-  for (CheckersOrdered::iterator I=CO->begin(), E=CO->end(); I!=E; ++I){
+  for (CheckersOrdered::iterator I=CO->begin(), E=CO->end(); I!=E; ++I) {
+    // If all nodes are sunk, bail out early.
+    if (PrevSet->empty())
+      break;
     ExplodedNodeSet *CurrSet = 0;
     if (I+1 == E)
       CurrSet = &Dst;
@@ -219,8 +223,8 @@ void GRExprEngine::CheckerVisit(Stmt *S, ExplodedNodeSet &Dst,
     for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
          NI != NE; ++NI) {
 
-      checker->GR_Visit(*CurrSet, *Builder, *this, S, *NI, tag, isPrevisit,
-                        respondsToCallback);
+      checker->GR_Visit(*CurrSet, *Builder, *this, S, *NI, tag,
+                        Kind == PreVisitStmtCallback, respondsToCallback);
       
     }
 
@@ -235,7 +239,9 @@ void GRExprEngine::CheckerVisit(Stmt *S, ExplodedNodeSet &Dst,
   
   // If we built NewCO, check if we called all the checkers.  This is important
   // so that we know that we accurately determined the entire set of checkers
-  // that responds to this callback.
+  // that responds to this callback.  Note that 'checkersEvaluated' might
+  // not be the same as Checkers.size() if one of the Checkers generates
+  // a sink node.
   if (NewCO.get() && checkersEvaluated == Checkers.size())
     CO_Ref = NewCO.take();
 
@@ -300,10 +306,9 @@ bool GRExprEngine::CheckerEvalCall(const CallExpr *CE,
 
 // FIXME: This is largely copy-paste from CheckerVisit().  Need to
 // unify.
-void GRExprEngine::CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE,
-                                    ExplodedNodeSet &Dst,
-                                    ExplodedNodeSet &Src,
-                                    SVal location, SVal val, bool isPrevisit) {
+void GRExprEngine::CheckerVisitBind(const Stmt *StoreE, ExplodedNodeSet &Dst,
+                                    ExplodedNodeSet &Src, SVal location,
+                                    SVal val, bool isPrevisit) {
 
   if (Checkers.empty()) {
     Dst.insert(Src);
@@ -328,7 +333,7 @@ void GRExprEngine::CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE,
 
     for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
          NI != NE; ++NI)
-      checker->GR_VisitBind(*CurrSet, *Builder, *this, AssignE, StoreE,
+      checker->GR_VisitBind(*CurrSet, *Builder, *this, StoreE,
                             *NI, tag, location, val, isPrevisit);
 
     // Update which NodeSet is the current one.
@@ -457,7 +462,7 @@ const GRState* GRExprEngine::getInitialState(const LocationContext *InitLoc) {
         break;
 
       SVal V = state->getSVal(loc::MemRegionVal(R));
-      SVal Constraint_untested = EvalBinOp(state, BinaryOperator::GT, V,
+      SVal Constraint_untested = EvalBinOp(state, BO_GT, V,
                                            ValMgr.makeZeroVal(T),
                                            getContext().IntTy);
 
@@ -499,29 +504,135 @@ const GRState* GRExprEngine::getInitialState(const LocationContext *InitLoc) {
 ///  logic for handling assumptions on symbolic values.
 const GRState *GRExprEngine::ProcessAssume(const GRState *state, SVal cond,
                                            bool assumption) {
-  for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end();
-        I != E; ++I) {
+  // Determine if we already have a cached 'CheckersOrdered' vector
+  // specifically tailored for processing assumptions.  This
+  // can reduce the number of checkers actually called.
+  CheckersOrdered *CO = &Checkers;
+  llvm::OwningPtr<CheckersOrdered> NewCO;
 
-    if (!state)
-      return NULL;
+  CallbackTag K = GetCallbackTag(ProcessAssumeCallback);
+  CheckersOrdered *& CO_Ref = COCache[K];
+
+  if (!CO_Ref) {
+    // If we have no previously cached CheckersOrdered vector for this
+    // statement kind, then create one.
+    NewCO.reset(new CheckersOrdered);
+  }
+  else {
+    // Use the already cached set.
+    CO = CO_Ref;
+  }
+
+  if (!CO->empty()) {
+    // Let the checkers have a crack at the assume before the transfer functions
+    // get their turn.
+    for (CheckersOrdered::iterator I = CO->begin(), E = CO->end(); I!=E; ++I) {
 
-    state = I->second->EvalAssume(state, cond, assumption);
+      // If any checker declares the state infeasible (or if it starts that
+      // way), bail out.
+      if (!state)
+        return NULL;
+
+      Checker *C = I->second;
+      bool respondsToCallback = true;
+
+      state = C->EvalAssume(state, cond, assumption, &respondsToCallback);
+
+      // Check if we're building the cache of checkers that care about Assumes.
+      if (NewCO.get() && respondsToCallback)
+        NewCO->push_back(*I);
+    }
+
+    // If we got through all the checkers, and we built a list of those that
+    // care about Assumes, save it.
+    if (NewCO.get())
+      CO_Ref = NewCO.take();
   }
 
+  // If the state is infeasible at this point, bail out.
   if (!state)
     return NULL;
 
   return TF->EvalAssume(state, cond, assumption);
 }
 
+bool GRExprEngine::WantsRegionChangeUpdate(const GRState* state) {
+  CallbackTag K = GetCallbackTag(EvalRegionChangesCallback);
+  CheckersOrdered *CO = COCache[K];
+
+  if (!CO)
+    CO = &Checkers;
+
+  for (CheckersOrdered::iterator I = CO->begin(), E = CO->end(); I != E; ++I) {
+    Checker *C = I->second;
+    if (C->WantsRegionChangeUpdate(state))
+      return true;
+  }
+
+  return false;
+}
+
+const GRState *
+GRExprEngine::ProcessRegionChanges(const GRState *state,
+                                   const MemRegion * const *Begin,
+                                   const MemRegion * const *End) {
+  // FIXME: Most of this method is copy-pasted from ProcessAssume.
+
+  // Determine if we already have a cached 'CheckersOrdered' vector
+  // specifically tailored for processing region changes.  This
+  // can reduce the number of checkers actually called.
+  CheckersOrdered *CO = &Checkers;
+  llvm::OwningPtr<CheckersOrdered> NewCO;
+
+  CallbackTag K = GetCallbackTag(EvalRegionChangesCallback);
+  CheckersOrdered *& CO_Ref = COCache[K];
+
+  if (!CO_Ref) {
+    // If we have no previously cached CheckersOrdered vector for this
+    // callback, then create one.
+    NewCO.reset(new CheckersOrdered);
+  }
+  else {
+    // Use the already cached set.
+    CO = CO_Ref;
+  }
+
+  // If there are no checkers, just return the state as is.
+  if (CO->empty())
+    return state;
+
+  for (CheckersOrdered::iterator I = CO->begin(), E = CO->end(); I != E; ++I) {
+    // If any checker declares the state infeasible (or if it starts that way),
+    // bail out.
+    if (!state)
+      return NULL;
+
+    Checker *C = I->second;
+    bool respondsToCallback = true;
+
+    state = C->EvalRegionChanges(state, Begin, End, &respondsToCallback);
+
+    // See if we're building a cache of checkers that care about region changes.
+    if (NewCO.get() && respondsToCallback)
+      NewCO->push_back(*I);
+  }
+
+  // If we got through all the checkers, and we built a list of those that
+  // care about region changes, save it.
+  if (NewCO.get())
+    CO_Ref = NewCO.take();
+
+  return state;
+}
+
 void GRExprEngine::ProcessEndWorklist(bool hasWorkRemaining) {
   for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end();
        I != E; ++I) {
-    I->second->VisitEndAnalysis(G, BR, hasWorkRemaining);
+    I->second->VisitEndAnalysis(G, BR, *this);
   }
 }
 
-void GRExprEngine::ProcessStmt(CFGElement CE, GRStmtNodeBuilder& builder) {
+void GRExprEngine::ProcessStmt(const CFGElement CE,GRStmtNodeBuilder& builder) {
   CurrentStmt = CE.getStmt();
   PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
                                 CurrentStmt->getLocStart(),
@@ -535,15 +646,23 @@ void GRExprEngine::ProcessStmt(CFGElement CE, GRStmtNodeBuilder& builder) {
     Builder->setAuditor(BatchAuditor.get());
 
   // Create the cleaned state.
-  const ExplodedNode *BasePred = Builder->getBasePredecessor();
+  const LocationContext *LC = EntryNode->getLocationContext();
+  SymbolReaper SymReaper(LC, CurrentStmt, SymMgr);
+
+  if (AMgr.shouldPurgeDead()) {
+    const GRState *St = EntryNode->getState();
 
-  SymbolReaper SymReaper(BasePred->getLocationContext(), CurrentStmt, SymMgr);
+    for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end();
+         I != E; ++I) {
+      Checker *checker = I->second;
+      checker->MarkLiveSymbols(St, SymReaper);
+    }
 
-  CleanedState = AMgr.shouldPurgeDead()
-    ? StateMgr.RemoveDeadBindings(EntryNode->getState(), 
-                         BasePred->getLocationContext()->getCurrentStackFrame(),
-                                  SymReaper)
-    : EntryNode->getState();
+    const StackFrameContext *SFC = LC->getCurrentStackFrame();
+    CleanedState = StateMgr.RemoveDeadBindings(St, SFC, SymReaper);
+  } else {
+    CleanedState = EntryNode->getState();
+  }
 
   // Process any special transfer function for dead symbols.
   ExplodedNodeSet Tmp;
@@ -625,7 +744,8 @@ void GRExprEngine::ProcessStmt(CFGElement CE, GRStmtNodeBuilder& builder) {
   Builder = NULL;
 }
 
-void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
+void GRExprEngine::Visit(const Stmt* S, ExplodedNode* Pred, 
+                         ExplodedNodeSet& Dst) {
   PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
                                 S->getLocStart(),
                                 "Error evaluating statement");
@@ -641,7 +761,6 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
 
   switch (S->getStmtClass()) {
     // C++ stuff we don't support yet.
-    case Stmt::CXXBindReferenceExprClass:
     case Stmt::CXXBindTemporaryExprClass:
     case Stmt::CXXCatchStmtClass:
     case Stmt::CXXConstructExprClass:
@@ -740,13 +859,13 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
       break;
 
     case Stmt::BinaryOperatorClass: {
-      BinaryOperator* B = cast<BinaryOperator>(S);
+      const BinaryOperator* B = cast<BinaryOperator>(S);
 
       if (B->isLogicalOp()) {
         VisitLogicalExpr(B, Pred, Dst);
         break;
       }
-      else if (B->getOpcode() == BinaryOperator::Comma) {
+      else if (B->getOpcode() == BO_Comma) {
         const GRState* state = GetState(Pred);
         MakeNode(Dst, B, Pred, state->BindExpr(B, state->getSVal(B->getRHS())));
         break;
@@ -766,25 +885,25 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
 
     case Stmt::CallExprClass:
     case Stmt::CXXOperatorCallExprClass: {
-      CallExpr* C = cast<CallExpr>(S);
+      const CallExpr* C = cast<CallExpr>(S);
       VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst, false);
       break;
     }
 
     case Stmt::CXXMemberCallExprClass: {
-      CXXMemberCallExpr *MCE = cast<CXXMemberCallExpr>(S);
+      const CXXMemberCallExpr *MCE = cast<CXXMemberCallExpr>(S);
       VisitCXXMemberCallExpr(MCE, Pred, Dst);
       break;
     }
 
     case Stmt::CXXNewExprClass: {
-      CXXNewExpr *NE = cast<CXXNewExpr>(S);
+      const CXXNewExpr *NE = cast<CXXNewExpr>(S);
       VisitCXXNewExpr(NE, Pred, Dst);
       break;
     }
 
     case Stmt::CXXDeleteExprClass: {
-      CXXDeleteExpr *CDE = cast<CXXDeleteExpr>(S);
+      const CXXDeleteExpr *CDE = cast<CXXDeleteExpr>(S);
       VisitCXXDeleteExpr(CDE, Pred, Dst);
       break;
     }
@@ -792,7 +911,7 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
       //        the CFG do not model them as explicit control-flow.
 
     case Stmt::ChooseExprClass: { // __builtin_choose_expr
-      ChooseExpr* C = cast<ChooseExpr>(S);
+      const ChooseExpr* C = cast<ChooseExpr>(S);
       VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
       break;
     }
@@ -806,7 +925,7 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
       break;
 
     case Stmt::ConditionalOperatorClass: { // '?' operator
-      ConditionalOperator* C = cast<ConditionalOperator>(S);
+      const ConditionalOperator* C = cast<ConditionalOperator>(S);
       VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
       break;
     }
@@ -836,7 +955,7 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
     case Stmt::CXXReinterpretCastExprClass:
     case Stmt::CXXConstCastExprClass:
     case Stmt::CXXFunctionalCastExprClass: {
-      CastExpr* C = cast<CastExpr>(S);
+      const CastExpr* C = cast<CastExpr>(S);
       VisitCast(C, C->getSubExpr(), Pred, Dst, false);
       break;
     }
@@ -893,7 +1012,7 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
       break;
 
     case Stmt::StmtExprClass: {
-      StmtExpr* SE = cast<StmtExpr>(S);
+      const StmtExpr* SE = cast<StmtExpr>(S);
 
       if (SE->getSubStmt()->body_empty()) {
         // Empty statement expression.
@@ -924,8 +1043,8 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
       break;
 
     case Stmt::UnaryOperatorClass: {
-      UnaryOperator *U = cast<UnaryOperator>(S);
-      if (AMgr.shouldEagerlyAssume()&&(U->getOpcode() == UnaryOperator::LNot)) {
+      const UnaryOperator *U = cast<UnaryOperator>(S);
+      if (AMgr.shouldEagerlyAssume()&&(U->getOpcode() == UO_LNot)) {
         ExplodedNodeSet Tmp;
         VisitUnaryOperator(U, Pred, Tmp, false);
         EvalEagerlyAssume(Dst, Tmp, U);
@@ -943,7 +1062,7 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
   }
 }
 
-void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
+void GRExprEngine::VisitLValue(const Expr* Ex, ExplodedNode* Pred,
                                ExplodedNodeSet& Dst) {
 
   PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
@@ -984,7 +1103,7 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
 
     case Stmt::CallExprClass:
     case Stmt::CXXOperatorCallExprClass: {
-      CallExpr *C = cast<CallExpr>(Ex);
+      const CallExpr *C = cast<CallExpr>(Ex);
       assert(CalleeReturnsReferenceOrRecord(C));
       VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst, true);
       break;
@@ -1000,7 +1119,7 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
 
     case Stmt::ImplicitCastExprClass:
     case Stmt::CStyleCastExprClass: {
-      CastExpr *C = cast<CastExpr>(Ex);
+      const CastExpr *C = cast<CastExpr>(Ex);
       QualType T = Ex->getType();
       VisitCast(C, C->getSubExpr(), Pred, Dst, true);
       break;
@@ -1015,7 +1134,7 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
       return;
 
     case Stmt::ObjCMessageExprClass: {
-      ObjCMessageExpr *ME = cast<ObjCMessageExpr>(Ex);
+      const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(Ex);
       assert(ReceiverReturnsReferenceOrRecord(ME));
       VisitObjCMessageExpr(ME, Pred, Dst, true);
       return;
@@ -1056,6 +1175,9 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
     // In C++, binding an rvalue to a reference requires to create an object.
     case Stmt::CXXBoolLiteralExprClass:
     case Stmt::IntegerLiteralClass:
+    case Stmt::CharacterLiteralClass:
+    case Stmt::FloatingLiteralClass:
+    case Stmt::ImaginaryLiteralClass:
       CreateCXXTemporaryObject(Ex, Pred, Dst);
       return;
 
@@ -1081,7 +1203,8 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
 // Block entrance.  (Update counters).
 //===----------------------------------------------------------------------===//
 
-bool GRExprEngine::ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred,
+bool GRExprEngine::ProcessBlockEntrance(const CFGBlock* B, 
+                                        const ExplodedNode *Pred,
                                         GRBlockCounter BC) {
   return BC.getNumVisited(Pred->getLocationContext()->getCurrentStackFrame(), 
                           B->getBlockID()) < AMgr.getMaxLoop();
@@ -1091,7 +1214,7 @@ bool GRExprEngine::ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred,
 // Generic node creation.
 //===----------------------------------------------------------------------===//
 
-ExplodedNode* GRExprEngine::MakeNode(ExplodedNodeSet& Dst, Stmt* S,
+ExplodedNode* GRExprEngine::MakeNode(ExplodedNodeSet& Dst, const Stmt* S,
                                      ExplodedNode* Pred, const GRState* St,
                                      ProgramPoint::Kind K, const void *tag) {
   assert (Builder && "GRStmtNodeBuilder not present.");
@@ -1105,8 +1228,8 @@ ExplodedNode* GRExprEngine::MakeNode(ExplodedNodeSet& Dst, Stmt* S,
 //===----------------------------------------------------------------------===//
 
 const GRState* GRExprEngine::MarkBranch(const GRState* state,
-                                           Stmt* Terminator,
-                                           bool branchTaken) {
+                                        const Stmt* Terminator,
+                                        bool branchTaken) {
 
   switch (Terminator->getStmtClass()) {
     default:
@@ -1114,10 +1237,10 @@ const GRState* GRExprEngine::MarkBranch(const GRState* state,
 
     case Stmt::BinaryOperatorClass: { // '&&' and '||'
 
-      BinaryOperator* B = cast<BinaryOperator>(Terminator);
+      const BinaryOperator* B = cast<BinaryOperator>(Terminator);
       BinaryOperator::Opcode Op = B->getOpcode();
 
-      assert (Op == BinaryOperator::LAnd || Op == BinaryOperator::LOr);
+      assert (Op == BO_LAnd || Op == BO_LOr);
 
       // For &&, if we take the true branch, then the value of the whole
       // expression is that of the RHS expression.
@@ -1125,21 +1248,21 @@ const GRState* GRExprEngine::MarkBranch(const GRState* state,
       // For ||, if we take the false branch, then the value of the whole
       // expression is that of the RHS expression.
 
-      Expr* Ex = (Op == BinaryOperator::LAnd && branchTaken) ||
-                 (Op == BinaryOperator::LOr && !branchTaken)
-               ? B->getRHS() : B->getLHS();
+      const Expr* Ex = (Op == BO_LAnd && branchTaken) ||
+                       (Op == BO_LOr && !branchTaken)
+                       ? B->getRHS() : B->getLHS();
 
       return state->BindExpr(B, UndefinedVal(Ex));
     }
 
     case Stmt::ConditionalOperatorClass: { // ?:
 
-      ConditionalOperator* C = cast<ConditionalOperator>(Terminator);
+      const ConditionalOperator* C = cast<ConditionalOperator>(Terminator);
 
       // For ?, if branchTaken == true then the value is either the LHS or
       // the condition itself. (GNU extension).
 
-      Expr* Ex;
+      const Expr* Ex;
 
       if (branchTaken)
         Ex = C->getLHS() ? C->getLHS() : C->getCond();
@@ -1151,9 +1274,9 @@ const GRState* GRExprEngine::MarkBranch(const GRState* state,
 
     case Stmt::ChooseExprClass: { // ?:
 
-      ChooseExpr* C = cast<ChooseExpr>(Terminator);
+      const ChooseExpr* C = cast<ChooseExpr>(Terminator);
 
-      Expr* Ex = branchTaken ? C->getLHS() : C->getRHS();
+      const Expr* Ex = branchTaken ? C->getLHS() : C->getRHS();
       return state->BindExpr(C, UndefinedVal(Ex));
     }
   }
@@ -1165,16 +1288,16 @@ const GRState* GRExprEngine::MarkBranch(const GRState* state,
 /// This function returns the SVal bound to Condition->IgnoreCasts if all the
 //  cast(s) did was sign-extend the original value.
 static SVal RecoverCastedSymbol(GRStateManager& StateMgr, const GRState* state,
-                                Stmt* Condition, ASTContext& Ctx) {
+                                const Stmt* Condition, ASTContext& Ctx) {
 
-  Expr *Ex = dyn_cast<Expr>(Condition);
+  const Expr *Ex = dyn_cast<Expr>(Condition);
   if (!Ex)
     return UnknownVal();
 
   uint64_t bits = 0;
   bool bitsInit = false;
 
-  while (CastExpr *CE = dyn_cast<CastExpr>(Ex)) {
+  while (const CastExpr *CE = dyn_cast<CastExpr>(Ex)) {
     QualType T = CE->getType();
 
     if (!T->isIntegerType())
@@ -1198,7 +1321,7 @@ static SVal RecoverCastedSymbol(GRStateManager& StateMgr, const GRState* state,
   return state->getSVal(Ex);
 }
 
-void GRExprEngine::ProcessBranch(Stmt* Condition, Stmt* Term,
+void GRExprEngine::ProcessBranch(const Stmt* Condition, const Stmt* Term,
                                  GRBranchNodeBuilder& builder) {
 
   // Check for NULL conditions; e.g. "for(;;)"
@@ -1285,7 +1408,7 @@ void GRExprEngine::ProcessIndirectGoto(GRIndirectGotoNodeBuilder& builder) {
   typedef GRIndirectGotoNodeBuilder::iterator iterator;
 
   if (isa<loc::GotoLabel>(V)) {
-    LabelStmt* L = cast<loc::GotoLabel>(V).getLabel();
+    const LabelStmt* L = cast<loc::GotoLabel>(V).getLabel();
 
     for (iterator I=builder.begin(), E=builder.end(); I != E; ++I) {
       if (I.getLabel() == L) {
@@ -1314,7 +1437,8 @@ void GRExprEngine::ProcessIndirectGoto(GRIndirectGotoNodeBuilder& builder) {
 }
 
 
-void GRExprEngine::VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R,
+void GRExprEngine::VisitGuardedExpr(const Expr* Ex, const Expr* L, 
+                                    const Expr* R,
                                     ExplodedNode* Pred, ExplodedNodeSet& Dst) {
 
   assert(Ex == CurrentStmt &&
@@ -1325,7 +1449,7 @@ void GRExprEngine::VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R,
 
   assert (X.isUndef());
 
-  Expr *SE = (Expr*) cast<UndefinedVal>(X).getData();
+  const Expr *SE = (Expr*) cast<UndefinedVal>(X).getData();
   assert(SE);
   X = state->getSVal(SE);
 
@@ -1350,7 +1474,7 @@ void GRExprEngine::ProcessEndPath(GREndPathNodeBuilder& builder) {
 void GRExprEngine::ProcessSwitch(GRSwitchNodeBuilder& builder) {
   typedef GRSwitchNodeBuilder::iterator iterator;
   const GRState* state = builder.getState();
-  Expr* CondE = builder.getCondition();
+  const Expr* CondE = builder.getCondition();
   SVal  CondV_untested = state->getSVal(CondE);
 
   if (CondV_untested.isUndef()) {
@@ -1363,10 +1487,12 @@ void GRExprEngine::ProcessSwitch(GRSwitchNodeBuilder& builder) {
   DefinedOrUnknownSVal CondV = cast<DefinedOrUnknownSVal>(CondV_untested);
 
   const GRState *DefaultSt = state;
-  bool defaultIsFeasible = false;
+  
+  iterator I = builder.begin(), EI = builder.end();
+  bool defaultIsFeasible = I == EI;
 
-  for (iterator I = builder.begin(), EI = builder.end(); I != EI; ++I) {
-    CaseStmt* Case = cast<CaseStmt>(I.getCase());
+  for ( ; I != EI; ++I) {
+    const CaseStmt* Case = I.getCase();
 
     // Evaluate the LHS of the case value.
     Expr::EvalResult V1;
@@ -1382,7 +1508,7 @@ void GRExprEngine::ProcessSwitch(GRSwitchNodeBuilder& builder) {
     // Get the RHS of the case, if it exists.
     Expr::EvalResult V2;
 
-    if (Expr* E = Case->getRHS()) {
+    if (const Expr* E = Case->getRHS()) {
       b = E->Evaluate(V2, getContext());
       assert(b && V2.Val.isInt() && !V2.HasSideEffects
              && "Case condition must evaluate to an integer constant.");
@@ -1440,15 +1566,14 @@ void GRExprEngine::ProcessSwitch(GRSwitchNodeBuilder& builder) {
 }
 
 void GRExprEngine::ProcessCallEnter(GRCallEnterNodeBuilder &B) {
-  const FunctionDecl *FD = B.getCallee();
-  const StackFrameContext *LocCtx = AMgr.getStackFrame(FD, 
-                                                       B.getLocationContext(),
-                                                       B.getCallExpr(),
-                                                       B.getBlock(),
-                                                       B.getIndex());
+  const StackFrameContext *LocCtx 
+    = AMgr.getStackFrame(B.getCalleeContext(),
+                         B.getLocationContext(),
+                         B.getCallExpr(),
+                         B.getBlock(),
+                         B.getIndex());
 
-  const GRState *state = B.getState();
-  state = getStoreManager().EnterStackFrame(state, LocCtx);
+  const GRState *state = B.getState()->EnterStackFrame(LocCtx);
 
   B.GenerateNode(state, LocCtx);
 }
@@ -1490,11 +1615,11 @@ void GRExprEngine::ProcessCallExit(GRCallExitNodeBuilder &B) {
 // Transfer functions: logical operations ('&&', '||').
 //===----------------------------------------------------------------------===//
 
-void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred,
+void GRExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode* Pred,
                                     ExplodedNodeSet& Dst) {
 
-  assert(B->getOpcode() == BinaryOperator::LAnd ||
-         B->getOpcode() == BinaryOperator::LOr);
+  assert(B->getOpcode() == BO_LAnd ||
+         B->getOpcode() == BO_LOr);
 
   assert(B==CurrentStmt && Pred->getLocationContext()->getCFG()->isBlkExpr(B));
 
@@ -1534,7 +1659,7 @@ void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred,
     // We took the LHS expression.  Depending on whether we are '&&' or
     // '||' we know what the value of the expression is via properties of
     // the short-circuiting.
-    X = ValMgr.makeIntVal(B->getOpcode() == BinaryOperator::LAnd ? 0U : 1U,
+    X = ValMgr.makeIntVal(B->getOpcode() == BO_LAnd ? 0U : 1U,
                           B->getType());
     MakeNode(Dst, B, Pred, state->BindExpr(B, X));
   }
@@ -1544,7 +1669,7 @@ void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred,
 // Transfer functions: Loads and stores.
 //===----------------------------------------------------------------------===//
 
-void GRExprEngine::VisitBlockExpr(BlockExpr *BE, ExplodedNode *Pred,
+void GRExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
                                   ExplodedNodeSet &Dst) {
 
   ExplodedNodeSet Tmp;
@@ -1557,21 +1682,21 @@ void GRExprEngine::VisitBlockExpr(BlockExpr *BE, ExplodedNode *Pred,
            ProgramPoint::PostLValueKind);
 
   // Post-visit the BlockExpr.
-  CheckerVisit(BE, Dst, Tmp, false);
+  CheckerVisit(BE, Dst, Tmp, PostVisitStmtCallback);
 }
 
-void GRExprEngine::VisitDeclRefExpr(DeclRefExpr *Ex, ExplodedNode *Pred,
+void GRExprEngine::VisitDeclRefExpr(const DeclRefExpr *Ex, ExplodedNode *Pred,
                                     ExplodedNodeSet &Dst, bool asLValue) {
   VisitCommonDeclRefExpr(Ex, Ex->getDecl(), Pred, Dst, asLValue);
 }
 
-void GRExprEngine::VisitBlockDeclRefExpr(BlockDeclRefExpr *Ex,
+void GRExprEngine::VisitBlockDeclRefExpr(const BlockDeclRefExpr *Ex,
                                          ExplodedNode *Pred,
                                     ExplodedNodeSet &Dst, bool asLValue) {
   VisitCommonDeclRefExpr(Ex, Ex->getDecl(), Pred, Dst, asLValue);
 }
 
-void GRExprEngine::VisitCommonDeclRefExpr(Expr *Ex, const NamedDecl *D,
+void GRExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
                                           ExplodedNode *Pred,
                                           ExplodedNodeSet &Dst, bool asLValue) {
 
@@ -1618,12 +1743,12 @@ void GRExprEngine::VisitCommonDeclRefExpr(Expr *Ex, const NamedDecl *D,
 }
 
 /// VisitArraySubscriptExpr - Transfer function for array accesses
-void GRExprEngine::VisitArraySubscriptExpr(ArraySubscriptExpr* A,
+void GRExprEngine::VisitArraySubscriptExpr(const ArraySubscriptExpr* A,
                                            ExplodedNode* Pred,
                                            ExplodedNodeSet& Dst, bool asLValue){
 
-  Expr* Base = A->getBase()->IgnoreParens();
-  Expr* Idx  = A->getIdx()->IgnoreParens();
+  const Expr* Base = A->getBase()->IgnoreParens();
+  const Expr* Idx  = A->getIdx()->IgnoreParens();
   ExplodedNodeSet Tmp;
 
   if (Base->getType()->isVectorType()) {
@@ -1641,7 +1766,7 @@ void GRExprEngine::VisitArraySubscriptExpr(ArraySubscriptExpr* A,
     Visit(Idx, *I1, Tmp2);     // Evaluate the index.
 
     ExplodedNodeSet Tmp3;
-    CheckerVisit(A, Tmp3, Tmp2, true);
+    CheckerVisit(A, Tmp3, Tmp2, PreVisitStmtCallback);
 
     for (ExplodedNodeSet::iterator I2=Tmp3.begin(),E2=Tmp3.end();I2!=E2; ++I2) {
       const GRState* state = GetState(*I2);
@@ -1658,7 +1783,7 @@ void GRExprEngine::VisitArraySubscriptExpr(ArraySubscriptExpr* A,
 }
 
 /// VisitMemberExpr - Transfer function for member expressions.
-void GRExprEngine::VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred,
+void GRExprEngine::VisitMemberExpr(const MemberExpr* M, ExplodedNode* Pred,
                                    ExplodedNodeSet& Dst, bool asLValue) {
 
   Expr* Base = M->getBase()->IgnoreParens();
@@ -1689,16 +1814,15 @@ void GRExprEngine::VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred,
 
 /// EvalBind - Handle the semantics of binding a value to a specific location.
 ///  This method is used by EvalStore and (soon) VisitDeclStmt, and others.
-void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, Stmt *AssignE,
-                            Stmt* StoreE, ExplodedNode* Pred,
-                            const GRState* state, SVal location, SVal Val,
-                            bool atDeclInit) {
+void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, const Stmt* StoreE,
+                            ExplodedNode* Pred, const GRState* state,
+                            SVal location, SVal Val, bool atDeclInit) {
 
 
   // Do a previsit of the bind.
   ExplodedNodeSet CheckedSet, Src;
   Src.Add(Pred);
-  CheckerVisitBind(AssignE, StoreE, CheckedSet, Src, location, Val, true);
+  CheckerVisitBind(StoreE, CheckedSet, Src, location, Val, true);
 
   for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
        I!=E; ++I) {
@@ -1731,6 +1855,10 @@ void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, Stmt *AssignE,
     // The next thing to do is check if the GRTransferFuncs object wants to
     // update the state based on the new binding.  If the GRTransferFunc object
     // doesn't do anything, just auto-propagate the current state.
+    
+    // NOTE: We use 'AssignE' for the location of the PostStore if 'AssignE'
+    // is non-NULL.  Checkers typically care about 
+    
     GRStmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, *I, newState, StoreE,
                                     newState != state);
 
@@ -1740,12 +1868,14 @@ void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, Stmt *AssignE,
 
 /// EvalStore - Handle the semantics of a store via an assignment.
 ///  @param Dst The node set to store generated state nodes
-///  @param Ex The expression representing the location of the store
+///  @param AssignE The assignment expression if the store happens in an 
+///         assignment.
+///  @param LocatioinE The location expression that is stored to.
 ///  @param state The current simulation state
 ///  @param location The location to store the value
 ///  @param Val The value to be stored
-void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, Expr *AssignE,
-                             Expr* StoreE,
+void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, const Expr *AssignE,
+                             const Expr* LocationE,
                              ExplodedNode* Pred,
                              const GRState* state, SVal location, SVal Val,
                              const void *tag) {
@@ -1754,7 +1884,7 @@ void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, Expr *AssignE,
 
   // Evaluate the location (checks for bad dereferences).
   ExplodedNodeSet Tmp;
-  EvalLocation(Tmp, StoreE, Pred, state, location, tag, false);
+  EvalLocation(Tmp, LocationE, Pred, state, location, tag, false);
 
   if (Tmp.empty())
     return;
@@ -1765,12 +1895,16 @@ void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, Expr *AssignE,
                                                    ProgramPoint::PostStoreKind);
   SaveAndRestore<const void*> OldTag(Builder->Tag, tag);
 
-  // Proceed with the store.
+  // Proceed with the store.  We use AssignE as the anchor for the PostStore
+  // ProgramPoint if it is non-NULL, and LocationE otherwise.
+  const Expr *StoreE = AssignE ? AssignE : LocationE;
+
   for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI)
-    EvalBind(Dst, AssignE, StoreE, *NI, GetState(*NI), location, Val);
+    EvalBind(Dst, StoreE, *NI, GetState(*NI), location, Val);
 }
 
-void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, Expr *Ex, ExplodedNode* Pred,
+void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, const Expr *Ex, 
+                            ExplodedNode* Pred,
                             const GRState* state, SVal location,
                             const void *tag, QualType LoadTy) {
 
@@ -1780,7 +1914,7 @@ void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, Expr *Ex, ExplodedNode* Pred,
   if (const TypedRegion *TR =
         dyn_cast_or_null<TypedRegion>(location.getAsRegion())) {
 
-    QualType ValTy = TR->getValueType(getContext());
+    QualType ValTy = TR->getValueType();
     if (const ReferenceType *RT = ValTy->getAs<ReferenceType>()) {
       static int loadReferenceTag = 0;
       ExplodedNodeSet Tmp;
@@ -1800,7 +1934,7 @@ void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, Expr *Ex, ExplodedNode* Pred,
   EvalLoadCommon(Dst, Ex, Pred, state, location, tag, LoadTy);
 }
 
-void GRExprEngine::EvalLoadCommon(ExplodedNodeSet& Dst, Expr *Ex,
+void GRExprEngine::EvalLoadCommon(ExplodedNodeSet& Dst, const Expr *Ex,
                                   ExplodedNode* Pred,
                                   const GRState* state, SVal location,
                                   const void *tag, QualType LoadTy) {
@@ -1834,7 +1968,7 @@ void GRExprEngine::EvalLoadCommon(ExplodedNodeSet& Dst, Expr *Ex,
   }
 }
 
-void GRExprEngine::EvalLocation(ExplodedNodeSet &Dst, Stmt *S,
+void GRExprEngine::EvalLocation(ExplodedNodeSet &Dst, const Stmt *S,
                                 ExplodedNode* Pred,
                                 const GRState* state, SVal location,
                                 const void *tag, bool isLoad) {
@@ -1885,21 +2019,34 @@ bool GRExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE,
   if (!FD)
     return false;
 
-  if (!FD->hasBody(FD))
-    return false;
+  // Check if the function definition is in the same translation unit.
+  if (FD->hasBody(FD)) {
+    // Now we have the definition of the callee, create a CallEnter node.
+    CallEnter Loc(CE, AMgr.getAnalysisContext(FD), Pred->getLocationContext());
+
+    ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
+    Dst.Add(N);
+    return true;
+  }
 
-  // Now we have the definition of the callee, create a CallEnter node.
-  CallEnter Loc(CE, FD, Pred->getLocationContext());
+  // Check if we can find the function definition in other translation units.
+  if (AMgr.hasIndexer()) {
+    const AnalysisContext *C = AMgr.getAnalysisContextInAnotherTU(FD);
+    if (C == 0)
+      return false;
 
-  ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
-  if (N)
+    CallEnter Loc(CE, C, Pred->getLocationContext());
+    ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
     Dst.Add(N);
-  return true;
+    return true;
+  }
+
+  return false;
 }
 
-void GRExprEngine::VisitCall(CallExpr* CE, ExplodedNode* Pred,
-                             CallExpr::arg_iterator AI,
-                             CallExpr::arg_iterator AE,
+void GRExprEngine::VisitCall(const CallExpr* CE, ExplodedNode* Pred,
+                             CallExpr::const_arg_iterator AI,
+                             CallExpr::const_arg_iterator AE,
                              ExplodedNodeSet& Dst, bool asLValue) {
 
   // Determine the type of function we're calling (if available).
@@ -1946,7 +2093,7 @@ void GRExprEngine::VisitCall(CallExpr* CE, ExplodedNode* Pred,
 
   // Now process the call itself.
   ExplodedNodeSet DstTmp;
-  Expr* Callee = CE->getCallee()->IgnoreParens();
+  const Expr* Callee = CE->getCallee()->IgnoreParens();
 
   for (ExplodedNodeSet::iterator NI=ArgsEvaluated.begin(),
                                  NE=ArgsEvaluated.end(); NI != NE; ++NI) {
@@ -1954,7 +2101,7 @@ void GRExprEngine::VisitCall(CallExpr* CE, ExplodedNode* Pred,
     ExplodedNodeSet DstTmp2;
     Visit(Callee, *NI, DstTmp2);
     // Perform the previsit of the CallExpr, storing the results in DstTmp.
-    CheckerVisit(CE, DstTmp, DstTmp2, true);
+    CheckerVisit(CE, DstTmp, DstTmp2, PreVisitStmtCallback);
   }
 
   // Finally, evaluate the function call.  We try each of the checkers
@@ -2009,7 +2156,7 @@ void GRExprEngine::VisitCall(CallExpr* CE, ExplodedNode* Pred,
   // If the callee returns a reference and we want an rvalue, skip this check
   // and do the load.
   if (!(!asLValue && CalleeReturnsReference(CE))) {
-    CheckerVisit(CE, Dst, DstTmp3, false);
+    CheckerVisit(CE, Dst, DstTmp3, PostVisitStmtCallback);
     return;
   }
 
@@ -2019,7 +2166,7 @@ void GRExprEngine::VisitCall(CallExpr* CE, ExplodedNode* Pred,
   // FIXME: This conversion doesn't actually happen unless the result
   //  of CallExpr is consumed by another expression.
   ExplodedNodeSet DstTmp4;
-  CheckerVisit(CE, DstTmp4, DstTmp3, false);
+  CheckerVisit(CE, DstTmp4, DstTmp3, PostVisitStmtCallback);
   QualType LoadTy = CE->getType();
 
   static int *ConvertToRvalueTag = 0;
@@ -2039,7 +2186,7 @@ static std::pair<const void*,const void*> EagerlyAssumeTag
   = std::pair<const void*,const void*>(&EagerlyAssumeTag,static_cast<void*>(0));
 
 void GRExprEngine::EvalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
-                                     Expr *Ex) {
+                                     const Expr *Ex) {
   for (ExplodedNodeSet::iterator I=Src.begin(), E=Src.end(); I!=E; ++I) {
     ExplodedNode *Pred = *I;
 
@@ -2082,10 +2229,11 @@ void GRExprEngine::EvalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
 // Transfer function: Objective-C ivar references.
 //===----------------------------------------------------------------------===//
 
-void GRExprEngine::VisitObjCIvarRefExpr(ObjCIvarRefExpr* Ex, ExplodedNode* Pred,
+void GRExprEngine::VisitObjCIvarRefExpr(const ObjCIvarRefExpr* Ex, 
+                                        ExplodedNode* Pred,
                                         ExplodedNodeSet& Dst, bool asLValue) {
 
-  Expr* Base = cast<Expr>(Ex->getBase());
+  const Expr* Base = cast<Expr>(Ex->getBase());
   ExplodedNodeSet Tmp;
   Visit(Base, Pred, Tmp);
 
@@ -2105,7 +2253,7 @@ void GRExprEngine::VisitObjCIvarRefExpr(ObjCIvarRefExpr* Ex, ExplodedNode* Pred,
 // Transfer function: Objective-C fast enumeration 'for' statements.
 //===----------------------------------------------------------------------===//
 
-void GRExprEngine::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S,
+void GRExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt* S,
                                      ExplodedNode* Pred, ExplodedNodeSet& Dst) {
 
   // ObjCForCollectionStmts are processed in two places.  This method
@@ -2133,11 +2281,11 @@ void GRExprEngine::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S,
   //    container is empty.  Thus this transfer function will by default
   //    result in state splitting.
 
-  Stmt* elem = S->getElement();
+  const Stmt* elem = S->getElement();
   SVal ElementV;
 
-  if (DeclStmt* DS = dyn_cast<DeclStmt>(elem)) {
-    VarDecl* ElemD = cast<VarDecl>(DS->getSingleDecl());
+  if (const DeclStmt* DS = dyn_cast<DeclStmt>(elem)) {
+    const VarDecl* ElemD = cast<VarDecl>(DS->getSingleDecl());
     assert (ElemD->getInit() == 0);
     ElementV = GetState(Pred)->getLValue(ElemD, Pred->getLocationContext());
     VisitObjCForCollectionStmtAux(S, Pred, Dst, ElementV);
@@ -2153,12 +2301,12 @@ void GRExprEngine::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S,
   }
 }
 
-void GRExprEngine::VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S,
+void GRExprEngine::VisitObjCForCollectionStmtAux(const ObjCForCollectionStmt* S,
                                        ExplodedNode* Pred, ExplodedNodeSet& Dst,
                                                  SVal ElementV) {
 
   // Check if the location we are writing back to is a null pointer.
-  Stmt* elem = S->getElement();
+  const Stmt* elem = S->getElement();
   ExplodedNodeSet Tmp;
   EvalLocation(Tmp, elem, Pred, GetState(Pred), ElementV, NULL, false);
 
@@ -2182,7 +2330,7 @@ void GRExprEngine::VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S,
         // FIXME: The proper thing to do is to really iterate over the
         //  container.  We will do this with dispatch logic to the store.
         //  For now, just 'conjure' up a symbolic value.
-        QualType T = R->getValueType(getContext());
+        QualType T = R->getValueType();
         assert(Loc::IsLocType(T));
         unsigned Count = Builder->getCurrentBlockCount();
         SymbolRef Sym = SymMgr.getConjuredSymbol(elem, T, Count);
@@ -2207,23 +2355,24 @@ void GRExprEngine::VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S,
 namespace {
 class ObjCMsgWLItem {
 public:
-  ObjCMessageExpr::arg_iterator I;
+  ObjCMessageExpr::const_arg_iterator I;
   ExplodedNode *N;
 
-  ObjCMsgWLItem(const ObjCMessageExpr::arg_iterator &i, ExplodedNode *n)
+  ObjCMsgWLItem(const ObjCMessageExpr::const_arg_iterator &i, ExplodedNode *n)
     : I(i), N(n) {}
 };
 } // end anonymous namespace
 
-void GRExprEngine::VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred,
+void GRExprEngine::VisitObjCMessageExpr(const ObjCMessageExpr* ME, 
+                                        ExplodedNode* Pred,
                                         ExplodedNodeSet& Dst, bool asLValue){
 
   // Create a worklist to process both the arguments.
   llvm::SmallVector<ObjCMsgWLItem, 20> WL;
 
   // But first evaluate the receiver (if any).
-  ObjCMessageExpr::arg_iterator AI = ME->arg_begin(), AE = ME->arg_end();
-  if (Expr *Receiver = ME->getInstanceReceiver()) {
+  ObjCMessageExpr::const_arg_iterator AI = ME->arg_begin(), AE = ME->arg_end();
+  if (const Expr *Receiver = ME->getInstanceReceiver()) {
     ExplodedNodeSet Tmp;
     Visit(Receiver, Pred, Tmp);
 
@@ -2261,7 +2410,7 @@ void GRExprEngine::VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred,
 
   // Now that the arguments are processed, handle the previsits checks.
   ExplodedNodeSet DstPrevisit;
-  CheckerVisit(ME, DstPrevisit, ArgsEvaluated, true);
+  CheckerVisit(ME, DstPrevisit, ArgsEvaluated, PreVisitStmtCallback);
 
   // Proceed with evaluate the message expression.
   ExplodedNodeSet DstEval;
@@ -2364,7 +2513,7 @@ void GRExprEngine::VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred,
   // Finally, perform the post-condition check of the ObjCMessageExpr and store
   // the created nodes in 'Dst'.
   if (!(!asLValue && ReceiverReturnsReference(ME))) {
-    CheckerVisit(ME, Dst, DstEval, false);
+    CheckerVisit(ME, Dst, DstEval, PostVisitStmtCallback);
     return;
   }
 
@@ -2374,7 +2523,7 @@ void GRExprEngine::VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred,
   // FIXME: This conversion doesn't actually happen unless the result
   //  of ObjCMessageExpr is consumed by another expression.
   ExplodedNodeSet DstRValueConvert;
-  CheckerVisit(ME, DstRValueConvert, DstEval, false);
+  CheckerVisit(ME, DstRValueConvert, DstEval, PostVisitStmtCallback);
   QualType LoadTy = ME->getType();
 
   static int *ConvertToRvalueTag = 0;
@@ -2390,8 +2539,9 @@ void GRExprEngine::VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred,
 // Transfer functions: Miscellaneous statements.
 //===----------------------------------------------------------------------===//
 
-void GRExprEngine::VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred,
-                             ExplodedNodeSet &Dst, bool asLValue) {
+void GRExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, 
+                             ExplodedNode *Pred, ExplodedNodeSet &Dst, 
+                             bool asLValue) {
   ExplodedNodeSet S1;
   QualType T = CastE->getType();
   QualType ExTy = Ex->getType();
@@ -2406,7 +2556,7 @@ void GRExprEngine::VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred,
     Visit(Ex, Pred, S1);
 
   ExplodedNodeSet S2;
-  CheckerVisit(CastE, S2, S1, true);
+  CheckerVisit(CastE, S2, S1, PreVisitStmtCallback);
 
   // If we are evaluating the cast in an lvalue context, we implicitly want
   // the cast to evaluate to a location.
@@ -2417,14 +2567,14 @@ void GRExprEngine::VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred,
   }
 
   switch (CastE->getCastKind()) {
-  case CastExpr::CK_ToVoid:
+  case CK_ToVoid:
     assert(!asLValue);
     for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I)
       Dst.Add(*I);
     return;
 
-  case CastExpr::CK_NoOp:
-  case CastExpr::CK_FunctionToPointerDecay:
+  case CK_NoOp:
+  case CK_FunctionToPointerDecay:
     for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
       // Copy the SVal of Ex to CastE.
       ExplodedNode *N = *I;
@@ -2435,20 +2585,21 @@ void GRExprEngine::VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred,
     }
     return;
 
-  case CastExpr::CK_Unknown:
-  case CastExpr::CK_ArrayToPointerDecay:
-  case CastExpr::CK_BitCast:
-  case CastExpr::CK_LValueBitCast:
-  case CastExpr::CK_IntegralCast:
-  case CastExpr::CK_IntegralToPointer:
-  case CastExpr::CK_PointerToIntegral:
-  case CastExpr::CK_IntegralToFloating:
-  case CastExpr::CK_FloatingToIntegral:
-  case CastExpr::CK_FloatingCast:
-  case CastExpr::CK_AnyPointerToObjCPointerCast:
-  case CastExpr::CK_AnyPointerToBlockPointerCast:
-  case CastExpr::CK_DerivedToBase:
-  case CastExpr::CK_UncheckedDerivedToBase: {
+  case CK_Unknown:
+  case CK_ArrayToPointerDecay:
+  case CK_BitCast:
+  case CK_LValueBitCast:
+  case CK_IntegralCast:
+  case CK_IntegralToPointer:
+  case CK_PointerToIntegral:
+  case CK_IntegralToFloating:
+  case CK_FloatingToIntegral:
+  case CK_FloatingCast:
+  case CK_AnyPointerToObjCPointerCast:
+  case CK_AnyPointerToBlockPointerCast:
+  case CK_DerivedToBase:
+  case CK_UncheckedDerivedToBase:
+  case CK_ObjCObjectLValueCast: {
     // Delegate to SValuator to process.
     for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
       ExplodedNode* N = *I;
@@ -2462,16 +2613,16 @@ void GRExprEngine::VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred,
   }
   
   // Various C++ casts that are not handled yet.
-  case CastExpr::CK_Dynamic:  
-  case CastExpr::CK_ToUnion:
-  case CastExpr::CK_BaseToDerived:
-  case CastExpr::CK_NullToMemberPointer:
-  case CastExpr::CK_BaseToDerivedMemberPointer:
-  case CastExpr::CK_DerivedToBaseMemberPointer:
-  case CastExpr::CK_UserDefinedConversion:
-  case CastExpr::CK_ConstructorConversion:
-  case CastExpr::CK_VectorSplat:
-  case CastExpr::CK_MemberPointerToBoolean: {
+  case CK_Dynamic:  
+  case CK_ToUnion:
+  case CK_BaseToDerived:
+  case CK_NullToMemberPointer:
+  case CK_BaseToDerivedMemberPointer:
+  case CK_DerivedToBaseMemberPointer:
+  case CK_UserDefinedConversion:
+  case CK_ConstructorConversion:
+  case CK_VectorSplat:
+  case CK_MemberPointerToBoolean: {
     SaveAndRestore<bool> OldSink(Builder->BuildSinks);
     Builder->BuildSinks = true;
     MakeNode(Dst, CastE, Pred, GetState(Pred));
@@ -2480,11 +2631,12 @@ void GRExprEngine::VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred,
   }
 }
 
-void GRExprEngine::VisitCompoundLiteralExpr(CompoundLiteralExpr* CL,
+void GRExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr* CL,
                                             ExplodedNode* Pred,
                                             ExplodedNodeSet& Dst,
                                             bool asLValue) {
-  InitListExpr* ILE = cast<InitListExpr>(CL->getInitializer()->IgnoreParens());
+  const InitListExpr* ILE 
+    = cast<InitListExpr>(CL->getInitializer()->IgnoreParens());
   ExplodedNodeSet Tmp;
   Visit(ILE, Pred, Tmp);
 
@@ -2502,17 +2654,17 @@ void GRExprEngine::VisitCompoundLiteralExpr(CompoundLiteralExpr* CL,
   }
 }
 
-void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred,
+void GRExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
                                  ExplodedNodeSet& Dst) {
 
   // The CFG has one DeclStmt per Decl.
-  Decl* D = *DS->decl_begin();
+  const Decl* D = *DS->decl_begin();
 
   if (!D || !isa<VarDecl>(D))
     return;
 
   const VarDecl* VD = dyn_cast<VarDecl>(D);
-  Expr* InitEx = const_cast<Expr*>(VD->getInit());
+  const Expr* InitEx = VD->getInit();
 
   // FIXME: static variables may have an initializer, but the second
   //  time a function is called those values may not be current.
@@ -2534,7 +2686,7 @@ void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred,
     Tmp.Add(Pred);
 
   ExplodedNodeSet Tmp2;
-  CheckerVisit(DS, Tmp2, Tmp, true);
+  CheckerVisit(DS, Tmp2, Tmp, PreVisitStmtCallback);
 
   for (ExplodedNodeSet::iterator I=Tmp2.begin(), E=Tmp2.end(); I!=E; ++I) {
     ExplodedNode *N = *I;
@@ -2555,7 +2707,7 @@ void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred,
                                                Builder->getCurrentBlockCount());
       }
 
-      EvalBind(Dst, DS, DS, *I, state,
+      EvalBind(Dst, DS, *I, state,
                loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true);
     }
     else {
@@ -2565,10 +2717,10 @@ void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred,
   }
 }
 
-void GRExprEngine::VisitCondInit(VarDecl *VD, Stmt *S,
+void GRExprEngine::VisitCondInit(const VarDecl *VD, const Stmt *S,
                                  ExplodedNode *Pred, ExplodedNodeSet& Dst) {
 
-  Expr* InitEx = VD->getInit();
+  const Expr* InitEx = VD->getInit();
   ExplodedNodeSet Tmp;
   Visit(InitEx, Pred, Tmp);
 
@@ -2587,7 +2739,7 @@ void GRExprEngine::VisitCondInit(VarDecl *VD, Stmt *S,
                                             Builder->getCurrentBlockCount());
     }
 
-    EvalBind(Dst, S, S, N, state,
+    EvalBind(Dst, S, N, state,
              loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true);
   }
 }
@@ -2599,16 +2751,16 @@ class InitListWLItem {
 public:
   llvm::ImmutableList<SVal> Vals;
   ExplodedNode* N;
-  InitListExpr::reverse_iterator Itr;
+  InitListExpr::const_reverse_iterator Itr;
 
   InitListWLItem(ExplodedNode* n, llvm::ImmutableList<SVal> vals,
-                 InitListExpr::reverse_iterator itr)
+                 InitListExpr::const_reverse_iterator itr)
   : Vals(vals), N(n), Itr(itr) {}
 };
 }
 
 
-void GRExprEngine::VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred,
+void GRExprEngine::VisitInitListExpr(const InitListExpr* E, ExplodedNode* Pred,
                                      ExplodedNodeSet& Dst) {
 
   const GRState* state = GetState(Pred);
@@ -2630,7 +2782,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred,
     llvm::SmallVector<InitListWLItem, 10> WorkList;
     WorkList.reserve(NumInitElements);
     WorkList.push_back(InitListWLItem(Pred, StartVals, E->rbegin()));
-    InitListExpr::reverse_iterator ItrEnd = E->rend();
+    InitListExpr::const_reverse_iterator ItrEnd = E->rend();
     assert(!(E->rbegin() == E->rend()));
 
     // Process the worklist until it is empty.
@@ -2641,7 +2793,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred,
       ExplodedNodeSet Tmp;
       Visit(*X.Itr, X.N, Tmp);
 
-      InitListExpr::reverse_iterator NewItr = X.Itr + 1;
+      InitListExpr::const_reverse_iterator NewItr = X.Itr + 1;
 
       for (ExplodedNodeSet::iterator NI=Tmp.begin(),NE=Tmp.end();NI!=NE;++NI) {
         // Get the last initializer value.
@@ -2673,7 +2825,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred,
   if (Loc::IsLocType(T) || T->isIntegerType()) {
     assert (E->getNumInits() == 1);
     ExplodedNodeSet Tmp;
-    Expr* Init = E->getInit(0);
+    const Expr* Init = E->getInit(0);
     Visit(Init, Pred, Tmp);
     for (ExplodedNodeSet::iterator I=Tmp.begin(), EI=Tmp.end(); I != EI; ++I) {
       state = GetState(*I);
@@ -2686,7 +2838,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred,
 }
 
 /// VisitSizeOfAlignOfExpr - Transfer function for sizeof(type).
-void GRExprEngine::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex,
+void GRExprEngine::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr* Ex,
                                           ExplodedNode* Pred,
                                           ExplodedNodeSet& Dst) {
   QualType T = Ex->getTypeOfArgument();
@@ -2709,7 +2861,7 @@ void GRExprEngine::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex,
 
       // Get the size by getting the extent of the sub-expression.
       // First, visit the sub-expression to find its region.
-      Expr *Arg = Ex->getArgumentExpr();
+      const Expr *Arg = Ex->getArgumentExpr();
       ExplodedNodeSet Tmp;
       VisitLValue(Arg, Pred, Tmp);
 
@@ -2751,8 +2903,8 @@ void GRExprEngine::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex,
               ValMgr.makeIntVal(amt.getQuantity(), Ex->getType())));
 }
 
-void GRExprEngine::VisitOffsetOfExpr(OffsetOfExpr* OOE, ExplodedNode* Pred,
-                                     ExplodedNodeSet& Dst) {
+void GRExprEngine::VisitOffsetOfExpr(const OffsetOfExpr* OOE, 
+                                     ExplodedNode* Pred, ExplodedNodeSet& Dst) {
   Expr::EvalResult Res;
   if (OOE->Evaluate(Res, getContext()) && Res.Val.isInt()) {
     const APSInt &IV = Res.Val.getInt();
@@ -2767,7 +2919,8 @@ void GRExprEngine::VisitOffsetOfExpr(OffsetOfExpr* OOE, ExplodedNode* Pred,
   Dst.Add(Pred);
 }
 
-void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
+void GRExprEngine::VisitUnaryOperator(const UnaryOperator* U, 
+                                      ExplodedNode* Pred,
                                       ExplodedNodeSet& Dst, bool asLValue) {
 
   switch (U->getOpcode()) {
@@ -2775,9 +2928,9 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
     default:
       break;
 
-    case UnaryOperator::Deref: {
+    case UO_Deref: {
 
-      Expr* Ex = U->getSubExpr()->IgnoreParens();
+      const Expr* Ex = U->getSubExpr()->IgnoreParens();
       ExplodedNodeSet Tmp;
       Visit(Ex, Pred, Tmp);
 
@@ -2796,9 +2949,9 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
       return;
     }
 
-    case UnaryOperator::Real: {
+    case UO_Real: {
 
-      Expr* Ex = U->getSubExpr()->IgnoreParens();
+      const Expr* Ex = U->getSubExpr()->IgnoreParens();
       ExplodedNodeSet Tmp;
       Visit(Ex, Pred, Tmp);
 
@@ -2811,7 +2964,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
           continue;
         }
 
-        // For all other types, UnaryOperator::Real is an identity operation.
+        // For all other types, UO_Real is an identity operation.
         assert (U->getType() == Ex->getType());
         const GRState* state = GetState(*I);
         MakeNode(Dst, U, *I, state->BindExpr(U, state->getSVal(Ex)));
@@ -2820,9 +2973,9 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
       return;
     }
 
-    case UnaryOperator::Imag: {
+    case UO_Imag: {
 
-      Expr* Ex = U->getSubExpr()->IgnoreParens();
+      const Expr* Ex = U->getSubExpr()->IgnoreParens();
       ExplodedNodeSet Tmp;
       Visit(Ex, Pred, Tmp);
 
@@ -2834,8 +2987,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
           continue;
         }
 
-        // For all other types, UnaryOperator::Float returns 0.
-        assert (Ex->getType()->isIntegerType());
+        // For all other types, UO_Imag returns 0.
         const GRState* state = GetState(*I);
         SVal X = ValMgr.makeZeroVal(Ex->getType());
         MakeNode(Dst, U, *I, state->BindExpr(U, X));
@@ -2843,38 +2995,22 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
 
       return;
     }
-
-    case UnaryOperator::OffsetOf: {
-      Expr::EvalResult Res;
-      if (U->Evaluate(Res, getContext()) && Res.Val.isInt()) {
-          const APSInt &IV = Res.Val.getInt();
-          assert(IV.getBitWidth() == getContext().getTypeSize(U->getType()));
-          assert(U->getType()->isIntegerType());
-          assert(IV.isSigned() == U->getType()->isSignedIntegerType());
-          SVal X = ValMgr.makeIntVal(IV);
-          MakeNode(Dst, U, Pred, GetState(Pred)->BindExpr(U, X));
-          return;
-        }
-      // FIXME: Handle the case where __builtin_offsetof is not a constant.
-      Dst.Add(Pred);
-      return;
-    }
       
-    case UnaryOperator::Plus: assert(!asLValue);  // FALL-THROUGH.
-    case UnaryOperator::Extension: {
+    case UO_Plus: assert(!asLValue);  // FALL-THROUGH.
+    case UO_Extension: {
 
       // Unary "+" is a no-op, similar to a parentheses.  We still have places
       // where it may be a block-level expression, so we need to
       // generate an extra node that just propagates the value of the
       // subexpression.
 
-      Expr* Ex = U->getSubExpr()->IgnoreParens();
+      const Expr* Ex = U->getSubExpr()->IgnoreParens();
       ExplodedNodeSet Tmp;
 
       if (asLValue)
-	VisitLValue(Ex, Pred, Tmp);
+        VisitLValue(Ex, Pred, Tmp);
       else
-	Visit(Ex, Pred, Tmp);
+        Visit(Ex, Pred, Tmp);
 
       for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
         const GRState* state = GetState(*I);
@@ -2884,10 +3020,10 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
       return;
     }
 
-    case UnaryOperator::AddrOf: {
+    case UO_AddrOf: {
 
       assert(!asLValue);
-      Expr* Ex = U->getSubExpr()->IgnoreParens();
+      const Expr* Ex = U->getSubExpr()->IgnoreParens();
       ExplodedNodeSet Tmp;
       VisitLValue(Ex, Pred, Tmp);
 
@@ -2901,12 +3037,12 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
       return;
     }
 
-    case UnaryOperator::LNot:
-    case UnaryOperator::Minus:
-    case UnaryOperator::Not: {
+    case UO_LNot:
+    case UO_Minus:
+    case UO_Not: {
 
       assert (!asLValue);
-      Expr* Ex = U->getSubExpr()->IgnoreParens();
+      const Expr* Ex = U->getSubExpr()->IgnoreParens();
       ExplodedNodeSet Tmp;
       Visit(Ex, Pred, Tmp);
 
@@ -2937,17 +3073,17 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
             assert(false && "Invalid Opcode.");
             break;
 
-          case UnaryOperator::Not:
+          case UO_Not:
             // FIXME: Do we need to handle promotions?
             state = state->BindExpr(U, EvalComplement(cast<NonLoc>(V)));
             break;
 
-          case UnaryOperator::Minus:
+          case UO_Minus:
             // FIXME: Do we need to handle promotions?
             state = state->BindExpr(U, EvalMinus(cast<NonLoc>(V)));
             break;
 
-          case UnaryOperator::LNot:
+          case UO_LNot:
 
             // C99 6.5.3.3: "The expression !E is equivalent to (0==E)."
             //
@@ -2957,12 +3093,12 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
 
             if (isa<Loc>(V)) {
               Loc X = ValMgr.makeNull();
-              Result = EvalBinOp(state, BinaryOperator::EQ, cast<Loc>(V), X,
+              Result = EvalBinOp(state, BO_EQ, cast<Loc>(V), X,
                                  U->getType());
             }
             else {
               nonloc::ConcreteInt X(getBasicVals().getValue(0, Ex->getType()));
-              Result = EvalBinOp(state, BinaryOperator::EQ, cast<NonLoc>(V), X,
+              Result = EvalBinOp(state, BO_EQ, cast<NonLoc>(V), X,
                                  U->getType());
             }
 
@@ -2982,7 +3118,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
 
   assert (U->isIncrementDecrementOp());
   ExplodedNodeSet Tmp;
-  Expr* Ex = U->getSubExpr()->IgnoreParens();
+  const Expr* Ex = U->getSubExpr()->IgnoreParens();
   VisitLValue(Ex, Pred, Tmp);
 
   for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) {
@@ -3007,8 +3143,8 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
       DefinedSVal V2 = cast<DefinedSVal>(V2_untested);
 
       // Handle all other values.
-      BinaryOperator::Opcode Op = U->isIncrementOp() ? BinaryOperator::Add
-                                                     : BinaryOperator::Sub;
+      BinaryOperator::Opcode Op = U->isIncrementOp() ? BO_Add
+                                                     : BO_Sub;
 
       // If the UnaryOperator has non-location type, use its type to create the
       // constant value. If the UnaryOperator has location type, create the
@@ -3057,14 +3193,14 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
   }
 }
 
-void GRExprEngine::VisitAsmStmt(AsmStmt* A, ExplodedNode* Pred,
+void GRExprEngine::VisitAsmStmt(const AsmStmt* A, ExplodedNode* Pred,
                                 ExplodedNodeSet& Dst) {
   VisitAsmStmtHelperOutputs(A, A->begin_outputs(), A->end_outputs(), Pred, Dst);
 }
 
-void GRExprEngine::VisitAsmStmtHelperOutputs(AsmStmt* A,
-                                             AsmStmt::outputs_iterator I,
-                                             AsmStmt::outputs_iterator E,
+void GRExprEngine::VisitAsmStmtHelperOutputs(const AsmStmt* A,
+                                             AsmStmt::const_outputs_iterator I,
+                                             AsmStmt::const_outputs_iterator E,
                                      ExplodedNode* Pred, ExplodedNodeSet& Dst) {
   if (I == E) {
     VisitAsmStmtHelperInputs(A, A->begin_inputs(), A->end_inputs(), Pred, Dst);
@@ -3080,9 +3216,9 @@ void GRExprEngine::VisitAsmStmtHelperOutputs(AsmStmt* A,
     VisitAsmStmtHelperOutputs(A, I, E, *NI, Dst);
 }
 
-void GRExprEngine::VisitAsmStmtHelperInputs(AsmStmt* A,
-                                            AsmStmt::inputs_iterator I,
-                                            AsmStmt::inputs_iterator E,
+void GRExprEngine::VisitAsmStmtHelperInputs(const AsmStmt* A,
+                                            AsmStmt::const_inputs_iterator I,
+                                            AsmStmt::const_inputs_iterator E,
                                             ExplodedNode* Pred,
                                             ExplodedNodeSet& Dst) {
   if (I == E) {
@@ -3096,7 +3232,7 @@ void GRExprEngine::VisitAsmStmtHelperInputs(AsmStmt* A,
 
     const GRState* state = GetState(Pred);
 
-    for (AsmStmt::outputs_iterator OI = A->begin_outputs(),
+    for (AsmStmt::const_outputs_iterator OI = A->begin_outputs(),
                                    OE = A->end_outputs(); OI != OE; ++OI) {
 
       SVal X = state->getSVal(*OI);
@@ -3119,10 +3255,10 @@ void GRExprEngine::VisitAsmStmtHelperInputs(AsmStmt* A,
     VisitAsmStmtHelperInputs(A, I, E, *NI, Dst);
 }
 
-void GRExprEngine::VisitReturnStmt(ReturnStmt *RS, ExplodedNode *Pred,
+void GRExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred,
                                    ExplodedNodeSet &Dst) {
   ExplodedNodeSet Src;
-  if (Expr *RetE = RS->getRetValue()) {
+  if (const Expr *RetE = RS->getRetValue()) {
     // Record the returned expression in the state. It will be used in
     // ProcessCallExit to bind the return value to the call expr.
     {
@@ -3141,7 +3277,7 @@ void GRExprEngine::VisitReturnStmt(ReturnStmt *RS, ExplodedNode *Pred,
   }
 
   ExplodedNodeSet CheckedSet;
-  CheckerVisit(RS, CheckedSet, Src, true);
+  CheckerVisit(RS, CheckedSet, Src, PreVisitStmtCallback);
 
   for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
        I != E; ++I) {
@@ -3167,7 +3303,7 @@ void GRExprEngine::VisitReturnStmt(ReturnStmt *RS, ExplodedNode *Pred,
 // Transfer functions: Binary operators.
 //===----------------------------------------------------------------------===//
 
-void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
+void GRExprEngine::VisitBinaryOperator(const BinaryOperator* B,
                                        ExplodedNode* Pred,
                                        ExplodedNodeSet& Dst, bool asLValue) {
 
@@ -3194,7 +3330,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
     Visit(RHS, *I1, Tmp2);
 
     ExplodedNodeSet CheckedSet;
-    CheckerVisit(B, CheckedSet, Tmp2, true);
+    CheckerVisit(B, CheckedSet, Tmp2, PreVisitStmtCallback);
 
     // With both the LHS and RHS evaluated, process the operation itself.
 
@@ -3207,13 +3343,13 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
 
       BinaryOperator::Opcode Op = B->getOpcode();
 
-      if (Op == BinaryOperator::Assign) {
+      if (Op == BO_Assign) {
         // EXPERIMENTAL: "Conjured" symbols.
         // FIXME: Handle structs.
         QualType T = RHS->getType();
 
-        if ((RightV.isUnknown()||!getConstraintManager().canReasonAbout(RightV))
-            && (Loc::IsLocType(T) || (T->isScalarType()&&T->isIntegerType()))) {
+        if (RightV.isUnknown() ||!getConstraintManager().canReasonAbout(RightV))
+        {
           unsigned Count = Builder->getCurrentBlockCount();
           RightV = ValMgr.getConjuredSymbolVal(NULL, B->getRHS(), Count);
         }
@@ -3253,16 +3389,16 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
       switch (Op) {
         default:
           assert(0 && "Invalid opcode for compound assignment.");
-        case BinaryOperator::MulAssign: Op = BinaryOperator::Mul; break;
-        case BinaryOperator::DivAssign: Op = BinaryOperator::Div; break;
-        case BinaryOperator::RemAssign: Op = BinaryOperator::Rem; break;
-        case BinaryOperator::AddAssign: Op = BinaryOperator::Add; break;
-        case BinaryOperator::SubAssign: Op = BinaryOperator::Sub; break;
-        case BinaryOperator::ShlAssign: Op = BinaryOperator::Shl; break;
-        case BinaryOperator::ShrAssign: Op = BinaryOperator::Shr; break;
-        case BinaryOperator::AndAssign: Op = BinaryOperator::And; break;
-        case BinaryOperator::XorAssign: Op = BinaryOperator::Xor; break;
-        case BinaryOperator::OrAssign:  Op = BinaryOperator::Or;  break;
+        case BO_MulAssign: Op = BO_Mul; break;
+        case BO_DivAssign: Op = BO_Div; break;
+        case BO_RemAssign: Op = BO_Rem; break;
+        case BO_AddAssign: Op = BO_Add; break;
+        case BO_SubAssign: Op = BO_Sub; break;
+        case BO_ShlAssign: Op = BO_Shl; break;
+        case BO_ShrAssign: Op = BO_Shr; break;
+        case BO_AndAssign: Op = BO_And; break;
+        case BO_XorAssign: Op = BO_Xor; break;
+        case BO_OrAssign:  Op = BO_Or;  break;
       }
 
       // Perform a load (the LHS).  This performs the checks for
@@ -3300,10 +3436,8 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
 
         SVal LHSVal;
 
-        if ((Result.isUnknown() ||
-             !getConstraintManager().canReasonAbout(Result))
-            && (Loc::IsLocType(CTy)
-                || (CTy->isScalarType() && CTy->isIntegerType()))) {
+        if (Result.isUnknown() ||
+            !getConstraintManager().canReasonAbout(Result)) {
 
           unsigned Count = Builder->getCurrentBlockCount();
 
@@ -3327,7 +3461,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
     }
   }
 
-  CheckerVisit(B, Dst, Tmp3, false);
+  CheckerVisit(B, Dst, Tmp3, PostVisitStmtCallback);
 }
 
 //===----------------------------------------------------------------------===//
@@ -3457,7 +3591,7 @@ struct DOTGraphTraits<ExplodedNode*> :
         Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
             << E.getDst()->getBlockID()  << ')';
 
-        if (Stmt* T = E.getSrc()->getTerminator()) {
+        if (const Stmt* T = E.getSrc()->getTerminator()) {
 
           SourceLocation SLoc = T->getLocStart();
 
@@ -3473,15 +3607,15 @@ struct DOTGraphTraits<ExplodedNode*> :
           }
 
           if (isa<SwitchStmt>(T)) {
-            Stmt* Label = E.getDst()->getLabel();
+            const Stmt* Label = E.getDst()->getLabel();
 
             if (Label) {
-              if (CaseStmt* C = dyn_cast<CaseStmt>(Label)) {
+              if (const CaseStmt* C = dyn_cast<CaseStmt>(Label)) {
                 Out << "\\lcase ";
                 LangOptions LO; // FIXME.
                 C->getLHS()->printPretty(Out, 0, PrintingPolicy(LO));
 
-                if (Stmt* RHS = C->getRHS()) {
+                if (const Stmt* RHS = C->getRHS()) {
                   Out << " .. ";
                   RHS->printPretty(Out, 0, PrintingPolicy(LO));
                 }
diff --git a/lib/Checker/GRExprEngineExperimentalChecks.cpp b/lib/Checker/GRExprEngineExperimentalChecks.cpp
index d138e81..84262b0 100644
--- a/lib/Checker/GRExprEngineExperimentalChecks.cpp
+++ b/lib/Checker/GRExprEngineExperimentalChecks.cpp
@@ -18,13 +18,14 @@
 
 using namespace clang;
 
-void clang::RegisterExperimentalChecks(GRExprEngine &Eng) {  
+void clang::RegisterExperimentalChecks(GRExprEngine &Eng) {
   // These are checks that never belong as internal checks
   // within GRExprEngine.
-  RegisterPthreadLockChecker(Eng);  
+  RegisterCStringChecker(Eng);
   RegisterMallocChecker(Eng);
+  RegisterPthreadLockChecker(Eng);
   RegisterStreamChecker(Eng);
-  RegisterCStringChecker(Eng);
+  RegisterUnreachableCodeChecker(Eng);
 }
 
 void clang::RegisterExperimentalInternalChecks(GRExprEngine &Eng) {
@@ -34,11 +35,10 @@ void clang::RegisterExperimentalInternalChecks(GRExprEngine &Eng) {
   // Note that this must be registered after ReturnStackAddresEngsChecker.
   RegisterReturnPointerRangeChecker(Eng);
   
+  RegisterArrayBoundChecker(Eng);
+  RegisterCastSizeChecker(Eng);
+  RegisterCastToStructChecker(Eng);
   RegisterFixedAddressChecker(Eng);
-  RegisterPointerSubChecker(Eng);
   RegisterPointerArithChecker(Eng);
-  RegisterCastToStructChecker(Eng);
-  RegisterCastSizeChecker(Eng);
-  RegisterArrayBoundChecker(Eng);
-
+  RegisterPointerSubChecker(Eng);
 }
diff --git a/lib/Checker/GRExprEngineExperimentalChecks.h b/lib/Checker/GRExprEngineExperimentalChecks.h
index 7d1eb77..7b5b0ed 100644
--- a/lib/Checker/GRExprEngineExperimentalChecks.h
+++ b/lib/Checker/GRExprEngineExperimentalChecks.h
@@ -20,10 +20,11 @@ namespace clang {
 class GRExprEngine;
 
 void RegisterCStringChecker(GRExprEngine &Eng);
-void RegisterPthreadLockChecker(GRExprEngine &Eng);
+void RegisterIdempotentOperationChecker(GRExprEngine &Eng);
 void RegisterMallocChecker(GRExprEngine &Eng);
+void RegisterPthreadLockChecker(GRExprEngine &Eng);
 void RegisterStreamChecker(GRExprEngine &Eng);
-void RegisterIdempotentOperationChecker(GRExprEngine &Eng);
+void RegisterUnreachableCodeChecker(GRExprEngine &Eng);
 
 } // end clang namespace
 #endif
diff --git a/lib/Checker/GRState.cpp b/lib/Checker/GRState.cpp
index 9e584b5..d38ae21 100644
--- a/lib/Checker/GRState.cpp
+++ b/lib/Checker/GRState.cpp
@@ -14,6 +14,7 @@
 #include "clang/Analysis/CFG.h"
 #include "clang/Checker/PathSensitive/GRStateTrait.h"
 #include "clang/Checker/PathSensitive/GRState.h"
+#include "clang/Checker/PathSensitive/GRSubEngine.h"
 #include "clang/Checker/PathSensitive/GRTransferFuncs.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -51,22 +52,105 @@ GRStateManager::RemoveDeadBindings(const GRState* state,
                                            state, RegionRoots);
 
   // Clean up the store.
-  const GRState *s = StoreMgr->RemoveDeadBindings(NewState, LCtx, 
-                                                  SymReaper, RegionRoots);
+  NewState.St = StoreMgr->RemoveDeadBindings(NewState.St, LCtx, 
+                                             SymReaper, RegionRoots);
+  state = getPersistentState(NewState);
+  return ConstraintMgr->RemoveDeadBindings(state, SymReaper);
+}
+
+const GRState *GRStateManager::MarshalState(const GRState *state,
+                                            const StackFrameContext *InitLoc) {
+  // make up an empty state for now.
+  GRState State(this,
+                EnvMgr.getInitialEnvironment(),
+                StoreMgr->getInitialStore(InitLoc),
+                GDMFactory.GetEmptyMap());
+
+  return getPersistentState(State);
+}
+
+const GRState *GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL,
+                                            const LocationContext *LC,
+                                            SVal V) const {
+  Store new_store = 
+    getStateManager().StoreMgr->BindCompoundLiteral(St, CL, LC, V);
+  return makeWithStore(new_store);
+}
+
+const GRState *GRState::bindDecl(const VarRegion* VR, SVal IVal) const {
+  Store new_store = getStateManager().StoreMgr->BindDecl(St, VR, IVal);
+  return makeWithStore(new_store);
+}
+
+const GRState *GRState::bindDeclWithNoInit(const VarRegion* VR) const {
+  Store new_store = getStateManager().StoreMgr->BindDeclWithNoInit(St, VR);
+  return makeWithStore(new_store);
+}
+
+const GRState *GRState::bindLoc(Loc LV, SVal V) const {
+  GRStateManager &Mgr = getStateManager();
+  Store new_store = Mgr.StoreMgr->Bind(St, LV, V);
+  const GRState *new_state = makeWithStore(new_store);
 
-  return ConstraintMgr->RemoveDeadBindings(s, SymReaper);
+  const MemRegion *MR = LV.getAsRegion();
+  if (MR)
+    return Mgr.getOwningEngine().ProcessRegionChange(new_state, MR);
+
+  return new_state;
+}
+
+const GRState *GRState::bindDefault(SVal loc, SVal V) const {
+  GRStateManager &Mgr = getStateManager();
+  const MemRegion *R = cast<loc::MemRegionVal>(loc).getRegion();
+  Store new_store = Mgr.StoreMgr->BindDefault(St, R, V);
+  const GRState *new_state = makeWithStore(new_store);
+  return Mgr.getOwningEngine().ProcessRegionChange(new_state, R);
+}
+
+const GRState *GRState::InvalidateRegions(const MemRegion * const *Begin,
+                                          const MemRegion * const *End,
+                                          const Expr *E, unsigned Count,
+                                          StoreManager::InvalidatedSymbols *IS,
+                                          bool invalidateGlobals) const {
+  GRStateManager &Mgr = getStateManager();
+  GRSubEngine &Eng = Mgr.getOwningEngine();
+
+  if (Eng.WantsRegionChangeUpdate(this)) {
+    StoreManager::InvalidatedRegions Regions;
+
+    Store new_store = Mgr.StoreMgr->InvalidateRegions(St, Begin, End,
+                                                      E, Count, IS,
+                                                      invalidateGlobals,
+                                                      &Regions);
+    const GRState *new_state = makeWithStore(new_store);
+
+    return Eng.ProcessRegionChanges(new_state,
+                                    &Regions.front(),
+                                    &Regions.back()+1);
+  }
+
+  Store new_store = Mgr.StoreMgr->InvalidateRegions(St, Begin, End,
+                                                    E, Count, IS,
+                                                    invalidateGlobals,
+                                                    NULL);
+  return makeWithStore(new_store);
 }
 
 const GRState *GRState::unbindLoc(Loc LV) const {
+  assert(!isa<loc::MemRegionVal>(LV) && "Use InvalidateRegion instead.");
+
   Store OldStore = getStore();
   Store NewStore = getStateManager().StoreMgr->Remove(OldStore, LV);
 
   if (NewStore == OldStore)
     return this;
 
-  GRState NewSt = *this;
-  NewSt.St = NewStore;
-  return getStateManager().getPersistentState(NewSt);
+  return makeWithStore(NewStore);
+}
+
+const GRState *GRState::EnterStackFrame(const StackFrameContext *frame) const {
+  Store new_store = getStateManager().StoreMgr->EnterStackFrame(this, frame);
+  return makeWithStore(new_store);
 }
 
 SVal GRState::getSValAsScalarOrLoc(const MemRegion *R) const {
@@ -77,7 +161,7 @@ SVal GRState::getSValAsScalarOrLoc(const MemRegion *R) const {
     return UnknownVal();
 
   if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {
-    QualType T = TR->getValueType(getStateManager().getContext());
+    QualType T = TR->getValueType();
     if (Loc::IsLocType(T) || T->isIntegerType())
       return getSVal(R);
   }
@@ -85,9 +169,45 @@ SVal GRState::getSValAsScalarOrLoc(const MemRegion *R) const {
   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,
+const GRState *GRState::BindExpr(const Stmt* S, SVal V, bool Invalidate) const{
+  Environment NewEnv = getStateManager().EnvMgr.bindExpr(Env, S, V,
                                                          Invalidate);
   if (NewEnv == Env)
     return this;
@@ -97,6 +217,63 @@ const GRState *GRState::BindExpr(const Stmt* Ex, SVal V, bool Invalidate) const{
   return getStateManager().getPersistentState(NewSt);
 }
 
+const GRState *GRState::bindExprAndLocation(const Stmt *S, SVal location,
+                                            SVal V) const {
+  Environment NewEnv =
+    getStateManager().EnvMgr.bindExprAndLocation(Env, S, location, V);
+
+  if (NewEnv == Env)
+    return this;
+  
+  GRState NewSt = *this;
+  NewSt.Env = NewEnv;
+  return getStateManager().getPersistentState(NewSt);
+}
+
+const GRState *GRState::AssumeInBound(DefinedOrUnknownSVal Idx,
+                                      DefinedOrUnknownSVal UpperBound,
+                                      bool Assumption) const {
+  if (Idx.isUnknown() || UpperBound.isUnknown())
+    return this;
+
+  // Build an expression for 0 <= Idx < UpperBound.
+  // This is the same as Idx + MIN < UpperBound + MIN, if overflow is allowed.
+  // FIXME: This should probably be part of SValuator.
+  GRStateManager &SM = getStateManager();
+  ValueManager &VM = SM.getValueManager();
+  SValuator &SV = VM.getSValuator();
+  ASTContext &Ctx = VM.getContext();
+
+  // Get the offset: the minimum value of the array index type.
+  BasicValueFactory &BVF = VM.getBasicValueFactory();
+  // FIXME: This should be using ValueManager::ArrayIndexTy...somehow.
+  QualType IndexTy = Ctx.IntTy;
+  nonloc::ConcreteInt Min = BVF.getMinValue(IndexTy);
+
+  // Adjust the index.
+  SVal NewIdx = SV.EvalBinOpNN(this, BO_Add,
+                               cast<NonLoc>(Idx), Min, IndexTy);
+  if (NewIdx.isUnknownOrUndef())
+    return this;
+
+  // Adjust the upper bound.
+  SVal NewBound = SV.EvalBinOpNN(this, BO_Add,
+                                 cast<NonLoc>(UpperBound), Min, IndexTy);
+  if (NewBound.isUnknownOrUndef())
+    return this;
+
+  // Build the actual comparison.
+  SVal InBound = SV.EvalBinOpNN(this, BO_LT,
+                                cast<NonLoc>(NewIdx), cast<NonLoc>(NewBound),
+                                Ctx.IntTy);
+  if (InBound.isUnknownOrUndef())
+    return this;
+
+  // Finally, let the constraint manager take care of it.
+  ConstraintManager &CM = SM.getConstraintManager();
+  return CM.Assume(this, cast<DefinedSVal>(InBound), Assumption);
+}
+
 const GRState* GRStateManager::getInitialState(const LocationContext *InitLoc) {
   GRState State(this,
                 EnvMgr.getInitialEnvironment(),
@@ -131,6 +308,11 @@ const GRState* GRState::makeWithStore(Store store) const {
 //  State pretty-printing.
 //===----------------------------------------------------------------------===//
 
+static bool IsEnvLoc(const Stmt *S) {
+  // FIXME: This is a layering violation.  Should be in environment.
+  return (bool) (((uintptr_t) S) & 0x1);
+}
+
 void GRState::print(llvm::raw_ostream& Out, CFG &C, const char* nl,
                     const char* sep) const {
   // Print the store.
@@ -140,8 +322,9 @@ void GRState::print(llvm::raw_ostream& Out, CFG &C, const char* nl,
   // Print Subexpression bindings.
   bool isFirst = true;
 
+  // FIXME: All environment printing should be moved inside Environment.
   for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) {
-    if (C.isBlkExpr(I.getKey()))
+    if (C.isBlkExpr(I.getKey()) || IsEnvLoc(I.getKey()))
       continue;
 
     if (isFirst) {
@@ -174,6 +357,27 @@ void GRState::print(llvm::raw_ostream& Out, CFG &C, const char* nl,
     I.getKey()->printPretty(Out, 0, PrintingPolicy(LO));
     Out << " : " << I.getData();
   }
+  
+  // Print locations.
+  isFirst = true;
+  
+  for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) {
+    if (!IsEnvLoc(I.getKey()))
+      continue;
+    
+    if (isFirst) {
+      Out << nl << nl << "Load/store locations:" << nl;
+      isFirst = false;
+    }
+    else { Out << nl; }
+
+    const Stmt *S = (Stmt*) (((uintptr_t) I.getKey()) & ((uintptr_t) ~0x1));
+    
+    Out << " (" << (void*) S << ") ";
+    LangOptions LO; // FIXME.
+    S->printPretty(Out, 0, PrintingPolicy(LO));
+    Out << " : " << I.getData();
+  }
 
   Mgr.getConstraintManager().print(this, Out, nl, sep);
 
diff --git a/lib/Checker/IdempotentOperationChecker.cpp b/lib/Checker/IdempotentOperationChecker.cpp
index 6ed1841..6411c79 100644
--- a/lib/Checker/IdempotentOperationChecker.cpp
+++ b/lib/Checker/IdempotentOperationChecker.cpp
@@ -36,25 +36,26 @@
 //  !=      |   0    |        |        |        |        |         |
 //===----------------------------------------------------------------------===//
 //
-// Ways to reduce false positives (that need to be implemented):
-// - Don't flag downsizing casts
-// - Improved handling of static/global variables
-// - Per-block marking of incomplete analysis
-// - Handling ~0 values
-// - False positives involving silencing unused variable warnings
-//
-// Other things TODO:
+// Things TODO:
 // - Improved error messages
 // - Handle mixed assumptions (which assumptions can belong together?)
 // - Finer grained false positive control (levels)
+// - Handling ~0 values
 
 #include "GRExprEngineExperimentalChecks.h"
+#include "clang/Analysis/CFGStmtMap.h"
+#include "clang/Analysis/Analyses/PseudoConstantAnalysis.h"
+#include "clang/Checker/BugReporter/BugReporter.h"
 #include "clang/Checker/BugReporter/BugType.h"
+#include "clang/Checker/PathSensitive/CheckerHelpers.h"
 #include "clang/Checker/PathSensitive/CheckerVisitor.h"
+#include "clang/Checker/PathSensitive/GRCoreEngine.h"
 #include "clang/Checker/PathSensitive/SVals.h"
 #include "clang/AST/Stmt.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/Support/ErrorHandling.h"
+#include <deque>
 
 using namespace clang;
 
@@ -64,38 +65,41 @@ class IdempotentOperationChecker
   public:
     static void *getTag();
     void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
-    void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B,
-        bool hasWorkRemaining);
+    void PostVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
+    void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B, GRExprEngine &Eng);
 
   private:
     // Our assumption about a particular operation.
-    enum Assumption { Possible, Impossible, Equal, LHSis1, RHSis1, LHSis0,
+    enum Assumption { Possible = 0, Impossible, Equal, LHSis1, RHSis1, LHSis0,
         RHSis0 };
 
     void UpdateAssumption(Assumption &A, const Assumption &New);
 
-    /// contains* - Useful recursive methods to see if a statement contains an
-    ///   element somewhere. Used in static analysis to reduce false positives.
-    static bool containsMacro(const Stmt *S);
-    static bool containsEnum(const Stmt *S);
-    static bool containsBuiltinOffsetOf(const Stmt *S);
-    static bool containsZeroConstant(const Stmt *S);
-    static bool containsOneConstant(const Stmt *S);
-    template <class T> static bool containsStmt(const Stmt *S) {
-      if (isa<T>(S))
-          return true;
-
-      for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
-          ++I)
-        if (const Stmt *child = *I)
-          if (containsStmt<T>(child))
-            return true;
-
-        return false;
-    }
-
-    // Hash table
-    typedef llvm::DenseMap<const BinaryOperator *, Assumption> AssumptionMap;
+    // False positive reduction methods
+    static bool isSelfAssign(const Expr *LHS, const Expr *RHS);
+    static bool isUnused(const Expr *E, AnalysisContext *AC);
+    //static bool isTruncationExtensionAssignment(const Expr *LHS,
+    //                                            const Expr *RHS);
+    static bool PathWasCompletelyAnalyzed(const CFG *C,
+                                          const CFGBlock *CB,
+                                          const GRCoreEngine &CE);
+    static bool CanVary(const Expr *Ex,
+                        AnalysisContext *AC);
+    static bool isConstantOrPseudoConstant(const DeclRefExpr *DR,
+                                           AnalysisContext *AC);
+    static bool containsNonLocalVarDecl(const Stmt *S);
+
+    // Hash table and related data structures
+    struct BinaryOperatorData {
+      BinaryOperatorData() : assumption(Possible), analysisContext(0) {}
+
+      Assumption assumption;
+      AnalysisContext *analysisContext;
+      ExplodedNodeSet explodedNodes; // Set of ExplodedNodes that refer to a
+                                     // BinaryOperator
+    };
+    typedef llvm::DenseMap<const BinaryOperator *, BinaryOperatorData>
+        AssumptionMap;
     AssumptionMap hash;
 };
 }
@@ -112,30 +116,38 @@ void clang::RegisterIdempotentOperationChecker(GRExprEngine &Eng) {
 void IdempotentOperationChecker::PreVisitBinaryOperator(
                                                       CheckerContext &C,
                                                       const BinaryOperator *B) {
-  // Find or create an entry in the hash for this BinaryOperator instance
-  AssumptionMap::iterator i = hash.find(B);
-  Assumption &A = i == hash.end() ? hash[B] : i->second;
-
-  // If we had to create an entry, initialise the value to Possible
-  if (i == hash.end())
-    A = Possible;
+  // Find or create an entry in the hash for this BinaryOperator instance.
+  // If we haven't done a lookup before, it will get default initialized to
+  // 'Possible'. At this stage we do not store the ExplodedNode, as it has not
+  // been created yet.
+  BinaryOperatorData &Data = hash[B];
+  Assumption &A = Data.assumption;
+  AnalysisContext *AC = C.getCurrentAnalysisContext();
+  Data.analysisContext = AC;
 
   // If we already have visited this node on a path that does not contain an
   // idempotent operation, return immediately.
   if (A == Impossible)
     return;
 
-  // Skip binary operators containing common false positives
-  if (containsMacro(B) || containsEnum(B) || containsStmt<SizeOfAlignOfExpr>(B)
-      || containsZeroConstant(B) || containsOneConstant(B)
-      || containsBuiltinOffsetOf(B)) {
-    A = Impossible;
-    return;
-  }
-
+  // Retrieve both sides of the operator and determine if they can vary (which
+  // may mean this is a false positive.
   const Expr *LHS = B->getLHS();
   const Expr *RHS = B->getRHS();
 
+  // At this stage we can calculate whether each side contains a false positive
+  // that applies to all operators. We only need to calculate this the first
+  // time.
+  bool LHSContainsFalsePositive = false, RHSContainsFalsePositive = false;
+  if (A == Possible) {
+    // An expression contains a false positive if it can't vary, or if it
+    // contains a known false positive VarDecl.
+    LHSContainsFalsePositive = !CanVary(LHS, AC)
+        || containsNonLocalVarDecl(LHS);
+    RHSContainsFalsePositive = !CanVary(RHS, AC)
+        || containsNonLocalVarDecl(RHS);
+  }
+
   const GRState *state = C.getState();
 
   SVal LHSVal = state->getSVal(LHS);
@@ -154,16 +166,16 @@ void IdempotentOperationChecker::PreVisitBinaryOperator(
     break;
 
   // Fall through intentional
-  case BinaryOperator::AddAssign:
-  case BinaryOperator::SubAssign:
-  case BinaryOperator::MulAssign:
-  case BinaryOperator::DivAssign:
-  case BinaryOperator::AndAssign:
-  case BinaryOperator::OrAssign:
-  case BinaryOperator::XorAssign:
-  case BinaryOperator::ShlAssign:
-  case BinaryOperator::ShrAssign:
-  case BinaryOperator::Assign:
+  case BO_AddAssign:
+  case BO_SubAssign:
+  case BO_MulAssign:
+  case BO_DivAssign:
+  case BO_AndAssign:
+  case BO_OrAssign:
+  case BO_XorAssign:
+  case BO_ShlAssign:
+  case BO_ShrAssign:
+  case BO_Assign:
   // Assign statements have one extra level of indirection
     if (!isa<Loc>(LHSVal)) {
       A = Impossible;
@@ -181,20 +193,37 @@ void IdempotentOperationChecker::PreVisitBinaryOperator(
     break; // We don't care about any other operators.
 
   // Fall through intentional
-  case BinaryOperator::SubAssign:
-  case BinaryOperator::DivAssign:
-  case BinaryOperator::AndAssign:
-  case BinaryOperator::OrAssign:
-  case BinaryOperator::XorAssign:
-  case BinaryOperator::Assign:
-  case BinaryOperator::Sub:
-  case BinaryOperator::Div:
-  case BinaryOperator::And:
-  case BinaryOperator::Or:
-  case BinaryOperator::Xor:
-  case BinaryOperator::LOr:
-  case BinaryOperator::LAnd:
-    if (LHSVal != RHSVal)
+  case BO_Assign:
+    // x Assign x can be used to silence unused variable warnings intentionally.
+    // If this is a self assignment and the variable is referenced elsewhere,
+    // then it is a false positive.
+    if (isSelfAssign(LHS, RHS)) {
+      if (!isUnused(LHS, AC)) {
+        UpdateAssumption(A, Equal);
+        return;
+      }
+      else {
+        A = Impossible;
+        return;
+      }
+    }
+
+  case BO_SubAssign:
+  case BO_DivAssign:
+  case BO_AndAssign:
+  case BO_OrAssign:
+  case BO_XorAssign:
+  case BO_Sub:
+  case BO_Div:
+  case BO_And:
+  case BO_Or:
+  case BO_Xor:
+  case BO_LOr:
+  case BO_LAnd:
+  case BO_EQ:
+  case BO_NE:
+    if (LHSVal != RHSVal || LHSContainsFalsePositive
+        || RHSContainsFalsePositive)
       break;
     UpdateAssumption(A, Equal);
     return;
@@ -206,13 +235,13 @@ void IdempotentOperationChecker::PreVisitBinaryOperator(
      break; // We don't care about any other operators.
 
    // Fall through intentional
-   case BinaryOperator::MulAssign:
-   case BinaryOperator::DivAssign:
-   case BinaryOperator::Mul:
-   case BinaryOperator::Div:
-   case BinaryOperator::LOr:
-   case BinaryOperator::LAnd:
-     if (!RHSVal.isConstant(1))
+   case BO_MulAssign:
+   case BO_DivAssign:
+   case BO_Mul:
+   case BO_Div:
+   case BO_LOr:
+   case BO_LAnd:
+     if (!RHSVal.isConstant(1) || RHSContainsFalsePositive)
        break;
      UpdateAssumption(A, RHSis1);
      return;
@@ -224,11 +253,11 @@ void IdempotentOperationChecker::PreVisitBinaryOperator(
     break; // We don't care about any other operators.
 
   // Fall through intentional
-  case BinaryOperator::MulAssign:
-  case BinaryOperator::Mul:
-  case BinaryOperator::LOr:
-  case BinaryOperator::LAnd:
-    if (!LHSVal.isConstant(1))
+  case BO_MulAssign:
+  case BO_Mul:
+  case BO_LOr:
+  case BO_LAnd:
+    if (!LHSVal.isConstant(1) || LHSContainsFalsePositive)
       break;
     UpdateAssumption(A, LHSis1);
     return;
@@ -240,23 +269,23 @@ void IdempotentOperationChecker::PreVisitBinaryOperator(
     break; // We don't care about any other operators.
 
   // Fall through intentional
-  case BinaryOperator::AddAssign:
-  case BinaryOperator::SubAssign:
-  case BinaryOperator::MulAssign:
-  case BinaryOperator::AndAssign:
-  case BinaryOperator::OrAssign:
-  case BinaryOperator::XorAssign:
-  case BinaryOperator::Add:
-  case BinaryOperator::Sub:
-  case BinaryOperator::Mul:
-  case BinaryOperator::And:
-  case BinaryOperator::Or:
-  case BinaryOperator::Xor:
-  case BinaryOperator::Shl:
-  case BinaryOperator::Shr:
-  case BinaryOperator::LOr:
-  case BinaryOperator::LAnd:
-    if (!RHSVal.isConstant(0))
+  case BO_AddAssign:
+  case BO_SubAssign:
+  case BO_MulAssign:
+  case BO_AndAssign:
+  case BO_OrAssign:
+  case BO_XorAssign:
+  case BO_Add:
+  case BO_Sub:
+  case BO_Mul:
+  case BO_And:
+  case BO_Or:
+  case BO_Xor:
+  case BO_Shl:
+  case BO_Shr:
+  case BO_LOr:
+  case BO_LAnd:
+    if (!RHSVal.isConstant(0) || RHSContainsFalsePositive)
       break;
     UpdateAssumption(A, RHSis0);
     return;
@@ -268,27 +297,27 @@ void IdempotentOperationChecker::PreVisitBinaryOperator(
     break; // We don't care about any other operators.
 
   // Fall through intentional
-  //case BinaryOperator::AddAssign: // Common false positive
-  case BinaryOperator::SubAssign: // Check only if unsigned
-  case BinaryOperator::MulAssign:
-  case BinaryOperator::DivAssign:
-  case BinaryOperator::AndAssign:
-  //case BinaryOperator::OrAssign: // Common false positive
-  //case BinaryOperator::XorAssign: // Common false positive
-  case BinaryOperator::ShlAssign:
-  case BinaryOperator::ShrAssign:
-  case BinaryOperator::Add:
-  case BinaryOperator::Sub:
-  case BinaryOperator::Mul:
-  case BinaryOperator::Div:
-  case BinaryOperator::And:
-  case BinaryOperator::Or:
-  case BinaryOperator::Xor:
-  case BinaryOperator::Shl:
-  case BinaryOperator::Shr:
-  case BinaryOperator::LOr:
-  case BinaryOperator::LAnd:
-    if (!LHSVal.isConstant(0))
+  //case BO_AddAssign: // Common false positive
+  case BO_SubAssign: // Check only if unsigned
+  case BO_MulAssign:
+  case BO_DivAssign:
+  case BO_AndAssign:
+  //case BO_OrAssign: // Common false positive
+  //case BO_XorAssign: // Common false positive
+  case BO_ShlAssign:
+  case BO_ShrAssign:
+  case BO_Add:
+  case BO_Sub:
+  case BO_Mul:
+  case BO_Div:
+  case BO_And:
+  case BO_Or:
+  case BO_Xor:
+  case BO_Shl:
+  case BO_Shr:
+  case BO_LOr:
+  case BO_LAnd:
+    if (!LHSVal.isConstant(0) || LHSContainsFalsePositive)
       break;
     UpdateAssumption(A, LHSis0);
     return;
@@ -298,47 +327,103 @@ void IdempotentOperationChecker::PreVisitBinaryOperator(
   A = Impossible;
 }
 
-void IdempotentOperationChecker::VisitEndAnalysis(ExplodedGraph &G,
-                                                  BugReporter &B,
-                                                  bool hasWorkRemaining) {
-  // If there is any work remaining we cannot be 100% sure about our warnings
-  if (hasWorkRemaining)
-    return;
+// At the post visit stage, the predecessor ExplodedNode will be the
+// BinaryOperator that was just created. We use this hook to collect the
+// ExplodedNode.
+void IdempotentOperationChecker::PostVisitBinaryOperator(
+                                                      CheckerContext &C,
+                                                      const BinaryOperator *B) {
+  // Add the ExplodedNode we just visited
+  BinaryOperatorData &Data = hash[B];
+  Data.explodedNodes.Add(C.getPredecessor());
+}
 
+void IdempotentOperationChecker::VisitEndAnalysis(ExplodedGraph &G,
+                                                  BugReporter &BR,
+                                                  GRExprEngine &Eng) {
+  BugType *BT = new BugType("Idempotent operation", "Dead code");
   // Iterate over the hash to see if we have any paths with definite
   // idempotent operations.
-  for (AssumptionMap::const_iterator i =
-      hash.begin(); i != hash.end(); ++i) {
-    if (i->second != Impossible) {
-      // Select the error message.
-      const char *msg = 0;
-      switch (i->second) {
-      case Equal:
-        msg = "idempotent operation; both operands are always equal in value";
-        break;
-      case LHSis1:
-        msg = "idempotent operation; the left operand is always 1";
-        break;
-      case RHSis1:
-        msg = "idempotent operation; the right operand is always 1";
-        break;
-      case LHSis0:
-        msg = "idempotent operation; the left operand is always 0";
-        break;
-      case RHSis0:
-        msg = "idempotent operation; the right operand is always 0";
-        break;
-      case Possible:
-        llvm_unreachable("Operation was never marked with an assumption");
-      case Impossible:
-        llvm_unreachable(0);
+  for (AssumptionMap::const_iterator i = hash.begin(); i != hash.end(); ++i) {
+    // Unpack the hash contents
+    const BinaryOperatorData &Data = i->second;
+    const Assumption &A = Data.assumption;
+    AnalysisContext *AC = Data.analysisContext;
+    const ExplodedNodeSet &ES = Data.explodedNodes;
+
+    const BinaryOperator *B = i->first;
+
+    if (A == Impossible)
+      continue;
+
+    // If the analyzer did not finish, check to see if we can still emit this
+    // warning
+    if (Eng.hasWorkRemaining()) {
+      const CFGStmtMap *CBM = CFGStmtMap::Build(AC->getCFG(),
+                                                &AC->getParentMap());
+
+      // If we can trace back
+      if (!PathWasCompletelyAnalyzed(AC->getCFG(),
+                                     CBM->getBlock(B),
+                                     Eng.getCoreEngine()))
+        continue;
+
+      delete CBM;
+    }
+
+    // Select the error message and SourceRanges to report.
+    llvm::SmallString<128> buf;
+    llvm::raw_svector_ostream os(buf);
+    bool LHSRelevant = false, RHSRelevant = false;
+    switch (A) {
+    case Equal:
+      LHSRelevant = true;
+      RHSRelevant = true;
+      if (B->getOpcode() == BO_Assign)
+        os << "Assigned value is always the same as the existing value";
+      else
+        os << "Both operands to '" << B->getOpcodeStr()
+           << "' always have the same value";
+      break;
+    case LHSis1:
+      LHSRelevant = true;
+      os << "The left operand to '" << B->getOpcodeStr() << "' is always 1";
+      break;
+    case RHSis1:
+      RHSRelevant = true;
+      os << "The right operand to '" << B->getOpcodeStr() << "' is always 1";
+      break;
+    case LHSis0:
+      LHSRelevant = true;
+      os << "The left operand to '" << B->getOpcodeStr() << "' is always 0";
+      break;
+    case RHSis0:
+      RHSRelevant = true;
+      os << "The right operand to '" << B->getOpcodeStr() << "' is always 0";
+      break;
+    case Possible:
+      llvm_unreachable("Operation was never marked with an assumption");
+    case Impossible:
+      llvm_unreachable(0);
+    }
+
+    // Add a report for each ExplodedNode
+    for (ExplodedNodeSet::iterator I = ES.begin(), E = ES.end(); I != E; ++I) {
+      EnhancedBugReport *report = new EnhancedBugReport(*BT, os.str(), *I);
+
+      // Add source ranges and visitor hooks
+      if (LHSRelevant) {
+        const Expr *LHS = i->first->getLHS();
+        report->addRange(LHS->getSourceRange());
+        report->addVisitorCreator(bugreporter::registerVarDeclsLastStore, LHS);
+      }
+      if (RHSRelevant) {
+        const Expr *RHS = i->first->getRHS();
+        report->addRange(i->first->getRHS()->getSourceRange());
+        report->addVisitorCreator(bugreporter::registerVarDeclsLastStore, RHS);
       }
 
-      // Create the SourceRange Arrays
-      SourceRange S[2] = { i->first->getLHS()->getSourceRange(),
-                           i->first->getRHS()->getSourceRange() };
-      B.EmitBasicReport("Idempotent operation", msg, i->first->getOperatorLoc(),
-          S, 2);
+      BR.EmitReport(report);
     }
   }
 }
@@ -346,6 +431,10 @@ void IdempotentOperationChecker::VisitEndAnalysis(ExplodedGraph &G,
 // Updates the current assumption given the new assumption
 inline void IdempotentOperationChecker::UpdateAssumption(Assumption &A,
                                                         const Assumption &New) {
+// If the assumption is the same, there is nothing to do
+  if (A == New)
+    return;
+
   switch (A) {
   // If we don't currently have an assumption, set it
   case Possible:
@@ -366,89 +455,249 @@ inline void IdempotentOperationChecker::UpdateAssumption(Assumption &A,
   }
 }
 
-// Recursively find any substatements containing macros
-bool IdempotentOperationChecker::containsMacro(const Stmt *S) {
-  if (S->getLocStart().isMacroID())
-    return true;
+// Check for a statement where a variable is self assigned to possibly avoid an
+// unused variable warning.
+bool IdempotentOperationChecker::isSelfAssign(const Expr *LHS, const Expr *RHS) {
+  LHS = LHS->IgnoreParenCasts();
+  RHS = RHS->IgnoreParenCasts();
 
-  if (S->getLocEnd().isMacroID())
-    return true;
+  const DeclRefExpr *LHS_DR = dyn_cast<DeclRefExpr>(LHS);
+  if (!LHS_DR)
+    return false;
 
-  for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
-      ++I)
-    if (const Stmt *child = *I)
-      if (containsMacro(child))
-        return true;
+  const VarDecl *VD = dyn_cast<VarDecl>(LHS_DR->getDecl());
+  if (!VD)
+    return false;
 
-  return false;
+  const DeclRefExpr *RHS_DR = dyn_cast<DeclRefExpr>(RHS);
+  if (!RHS_DR)
+    return false;
+
+  if (VD != RHS_DR->getDecl())
+    return false;
+
+  return true;
 }
 
-// Recursively find any substatements containing enum constants
-bool IdempotentOperationChecker::containsEnum(const Stmt *S) {
-  const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S);
+// Returns true if the Expr points to a VarDecl that is not read anywhere
+// outside of self-assignments.
+bool IdempotentOperationChecker::isUnused(const Expr *E,
+                                          AnalysisContext *AC) {
+  if (!E)
+    return false;
 
-  if (DR && isa<EnumConstantDecl>(DR->getDecl()))
-    return true;
+  const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts());
+  if (!DR)
+    return false;
 
-  for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
-      ++I)
-    if (const Stmt *child = *I)
-      if (containsEnum(child))
-        return true;
+  const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
+  if (!VD)
+    return false;
 
-  return false;
+  if (AC->getPseudoConstantAnalysis()->wasReferenced(VD))
+    return false;
+
+  return true;
 }
 
-// Recursively find any substatements containing __builtin_offset_of
-bool IdempotentOperationChecker::containsBuiltinOffsetOf(const Stmt *S) {
-  const UnaryOperator *UO = dyn_cast<UnaryOperator>(S);
+#if 0
+// Check for self casts truncating/extending a variable
+bool IdempotentOperationChecker::isTruncationExtensionAssignment(
+                                                              const Expr *LHS,
+                                                              const Expr *RHS) {
 
-  if (UO && UO->getOpcode() == UnaryOperator::OffsetOf)
-    return true;
+  const DeclRefExpr *LHS_DR = dyn_cast<DeclRefExpr>(LHS->IgnoreParenCasts());
+  if (!LHS_DR)
+    return false;
 
-  for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
-      ++I)
-    if (const Stmt *child = *I)
-      if (containsBuiltinOffsetOf(child))
-        return true;
+  const VarDecl *VD = dyn_cast<VarDecl>(LHS_DR->getDecl());
+  if (!VD)
+    return false;
 
-  return false;
+  const DeclRefExpr *RHS_DR = dyn_cast<DeclRefExpr>(RHS->IgnoreParenCasts());
+  if (!RHS_DR)
+    return false;
+
+  if (VD != RHS_DR->getDecl())
+     return false;
+
+  return dyn_cast<DeclRefExpr>(RHS->IgnoreParens()) == NULL;
 }
+#endif
+
+// Returns false if a path to this block was not completely analyzed, or true
+// otherwise.
+bool IdempotentOperationChecker::PathWasCompletelyAnalyzed(
+                                                       const CFG *C,
+                                                       const CFGBlock *CB,
+                                                       const GRCoreEngine &CE) {
+  std::deque<const CFGBlock *> WorkList;
+  llvm::SmallSet<unsigned, 8> Aborted;
+  llvm::SmallSet<unsigned, 128> Visited;
+
+  // Create a set of all aborted blocks
+  typedef GRCoreEngine::BlocksAborted::const_iterator AbortedIterator;
+  for (AbortedIterator I = CE.blocks_aborted_begin(),
+      E = CE.blocks_aborted_end(); I != E; ++I) {
+    const BlockEdge &BE =  I->first;
+
+    // The destination block on the BlockEdge is the first block that was not
+    // analyzed.
+    Aborted.insert(BE.getDst()->getBlockID());
+  }
 
-bool IdempotentOperationChecker::containsZeroConstant(const Stmt *S) {
-  const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(S);
-  if (IL && IL->getValue() == 0)
+  // Save the entry block ID for early exiting
+  unsigned EntryBlockID = C->getEntry().getBlockID();
+
+  // Create initial node
+  WorkList.push_back(CB);
+
+  while (!WorkList.empty()) {
+    const CFGBlock *Head = WorkList.front();
+    WorkList.pop_front();
+    Visited.insert(Head->getBlockID());
+
+    // If we found the entry block, then there exists a path from the target
+    // node to the entry point of this function -> the path was completely
+    // analyzed.
+    if (Head->getBlockID() == EntryBlockID)
+      return true;
+
+    // If any of the aborted blocks are on the path to the beginning, then all
+    // paths to this block were not analyzed.
+    if (Aborted.count(Head->getBlockID()))
+      return false;
+
+    // Add the predecessors to the worklist unless we have already visited them
+    for (CFGBlock::const_pred_iterator I = Head->pred_begin();
+        I != Head->pred_end(); ++I)
+      if (!Visited.count((*I)->getBlockID()))
+        WorkList.push_back(*I);
+  }
+
+  // If we get to this point, there is no connection to the entry block or an
+  // aborted block. This path is unreachable and we can report the error.
+  return true;
+}
+
+// Recursive function that determines whether an expression contains any element
+// that varies. This could be due to a compile-time constant like sizeof. An
+// expression may also involve a variable that behaves like a constant. The
+// function returns true if the expression varies, and false otherwise.
+bool IdempotentOperationChecker::CanVary(const Expr *Ex,
+                                         AnalysisContext *AC) {
+  // Parentheses and casts are irrelevant here
+  Ex = Ex->IgnoreParenCasts();
+
+  if (Ex->getLocStart().isMacroID())
+    return false;
+
+  switch (Ex->getStmtClass()) {
+  // Trivially true cases
+  case Stmt::ArraySubscriptExprClass:
+  case Stmt::MemberExprClass:
+  case Stmt::StmtExprClass:
+  case Stmt::CallExprClass:
+  case Stmt::VAArgExprClass:
+  case Stmt::ShuffleVectorExprClass:
+    return true;
+  default:
     return true;
 
-  const FloatingLiteral *FL = dyn_cast<FloatingLiteral>(S);
-  if (FL && FL->getValue().isZero())
+  // Trivially false cases
+  case Stmt::IntegerLiteralClass:
+  case Stmt::CharacterLiteralClass:
+  case Stmt::FloatingLiteralClass:
+  case Stmt::PredefinedExprClass:
+  case Stmt::ImaginaryLiteralClass:
+  case Stmt::StringLiteralClass:
+  case Stmt::OffsetOfExprClass:
+  case Stmt::CompoundLiteralExprClass:
+  case Stmt::AddrLabelExprClass:
+  case Stmt::TypesCompatibleExprClass:
+  case Stmt::GNUNullExprClass:
+  case Stmt::InitListExprClass:
+  case Stmt::DesignatedInitExprClass:
+  case Stmt::BlockExprClass:
+  case Stmt::BlockDeclRefExprClass:
+    return false;
+
+  // Cases requiring custom logic
+  case Stmt::SizeOfAlignOfExprClass: {
+    const SizeOfAlignOfExpr *SE = cast<const SizeOfAlignOfExpr>(Ex);
+    if (!SE->isSizeOf())
+      return false;
+    return SE->getTypeOfArgument()->isVariableArrayType();
+  }
+  case Stmt::DeclRefExprClass:
+    // Check for constants/pseudoconstants
+    return !isConstantOrPseudoConstant(cast<DeclRefExpr>(Ex), AC);
+
+  // The next cases require recursion for subexpressions
+  case Stmt::BinaryOperatorClass: {
+    const BinaryOperator *B = cast<const BinaryOperator>(Ex);
+    return CanVary(B->getRHS(), AC)
+        || CanVary(B->getLHS(), AC);
+   }
+  case Stmt::UnaryOperatorClass: {
+    const UnaryOperator *U = cast<const UnaryOperator>(Ex);
+    // Handle trivial case first
+    switch (U->getOpcode()) {
+    case UO_Extension:
+      return false;
+    default:
+      return CanVary(U->getSubExpr(), AC);
+    }
+  }
+  case Stmt::ChooseExprClass:
+    return CanVary(cast<const ChooseExpr>(Ex)->getChosenSubExpr(
+        AC->getASTContext()), AC);
+  case Stmt::ConditionalOperatorClass:
+    return CanVary(cast<const ConditionalOperator>(Ex)->getCond(), AC);
+  }
+}
+
+// Returns true if a DeclRefExpr is or behaves like a constant.
+bool IdempotentOperationChecker::isConstantOrPseudoConstant(
+                                                          const DeclRefExpr *DR,
+                                                          AnalysisContext *AC) {
+  // Check if the type of the Decl is const-qualified
+  if (DR->getType().isConstQualified())
     return true;
 
-  for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
-      ++I)
-    if (const Stmt *child = *I)
-      if (containsZeroConstant(child))
-        return true;
+  // Check for an enum
+  if (isa<EnumConstantDecl>(DR->getDecl()))
+    return true;
+
+  const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
+  if (!VD)
+    return true;
+
+  // Check if the Decl behaves like a constant. This check also takes care of
+  // static variables, which can only change between function calls if they are
+  // modified in the AST.
+  PseudoConstantAnalysis *PCA = AC->getPseudoConstantAnalysis();
+  if (PCA->isPseudoConstant(VD))
+    return true;
 
   return false;
 }
 
-bool IdempotentOperationChecker::containsOneConstant(const Stmt *S) {
-  const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(S);
-  if (IL && IL->getValue() == 1)
-    return true;
+// Recursively find any substatements containing VarDecl's with storage other
+// than local
+bool IdempotentOperationChecker::containsNonLocalVarDecl(const Stmt *S) {
+  const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S);
 
-  const FloatingLiteral *FL = dyn_cast<FloatingLiteral>(S);
-  const llvm::APFloat one(1.0);
-  if (FL && FL->getValue().compare(one) == llvm::APFloat::cmpEqual)
-    return true;
+  if (DR)
+    if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
+      if (!VD->hasLocalStorage())
+        return true;
 
   for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
       ++I)
     if (const Stmt *child = *I)
-      if (containsOneConstant(child))
+      if (containsNonLocalVarDecl(child))
         return true;
 
   return false;
 }
-
diff --git a/lib/Checker/LLVMConventionsChecker.cpp b/lib/Checker/LLVMConventionsChecker.cpp
index c121257..2f87da1 100644
--- a/lib/Checker/LLVMConventionsChecker.cpp
+++ b/lib/Checker/LLVMConventionsChecker.cpp
@@ -128,7 +128,6 @@ public:
   void VisitDeclStmt(DeclStmt *DS);
 private:
   void VisitVarDecl(VarDecl *VD);
-  void CheckStringRefBoundtoTemporaryString(VarDecl *VD);
 };
 } // end anonymous namespace
 
diff --git a/lib/Checker/Makefile b/lib/Checker/Makefile
index 1bc6529..4ec6f65 100644
--- a/lib/Checker/Makefile
+++ b/lib/Checker/Makefile
@@ -13,7 +13,6 @@
 
 CLANG_LEVEL := ../..
 LIBRARYNAME := clangChecker
-BUILD_ARCHIVE = 1
 
 include $(CLANG_LEVEL)/Makefile
 
diff --git a/lib/Checker/MallocChecker.cpp b/lib/Checker/MallocChecker.cpp
index dcc21ca..c9b6d75 100644
--- a/lib/Checker/MallocChecker.cpp
+++ b/lib/Checker/MallocChecker.cpp
@@ -24,15 +24,18 @@ using namespace clang;
 namespace {
 
 class RefState {
-  enum Kind { AllocateUnchecked, AllocateFailed, Released, Escaped } K;
+  enum Kind { AllocateUnchecked, AllocateFailed, Released, Escaped,
+              Relinquished } K;
   const Stmt *S;
 
 public:
   RefState(Kind k, const Stmt *s) : K(k), S(s) {}
 
   bool isAllocated() const { return K == AllocateUnchecked; }
+  //bool isFailed() const { return K == AllocateFailed; }
   bool isReleased() const { return K == Released; }
-  bool isEscaped() const { return K == Escaped; }
+  //bool isEscaped() const { return K == Escaped; }
+  //bool isRelinquished() const { return K == Relinquished; }
 
   bool operator==(const RefState &X) const {
     return K == X.K && S == X.S;
@@ -46,6 +49,9 @@ public:
   }
   static RefState getReleased(const Stmt *s) { return RefState(Released, s); }
   static RefState getEscaped(const Stmt *s) { return RefState(Escaped, s); }
+  static RefState getRelinquished(const Stmt *s) {
+    return RefState(Relinquished, s);
+  }
 
   void Profile(llvm::FoldingSetNodeID &ID) const {
     ID.AddInteger(K);
@@ -59,23 +65,30 @@ class MallocChecker : public CheckerVisitor<MallocChecker> {
   BuiltinBug *BT_DoubleFree;
   BuiltinBug *BT_Leak;
   BuiltinBug *BT_UseFree;
+  BuiltinBug *BT_UseRelinquished;
   BuiltinBug *BT_BadFree;
   IdentifierInfo *II_malloc, *II_free, *II_realloc, *II_calloc;
 
 public:
   MallocChecker() 
-    : BT_DoubleFree(0), BT_Leak(0), BT_UseFree(0), BT_BadFree(0),
+    : BT_DoubleFree(0), BT_Leak(0), BT_UseFree(0), BT_UseRelinquished(0),
+      BT_BadFree(0),
       II_malloc(0), II_free(0), II_realloc(0), II_calloc(0) {}
   static void *getTag();
   bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
   void EvalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper);
   void EvalEndPath(GREndPathNodeBuilder &B, void *tag, GRExprEngine &Eng);
   void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S);
-  const GRState *EvalAssume(const GRState *state, SVal Cond, bool Assumption);
+  const GRState *EvalAssume(const GRState *state, SVal Cond, bool Assumption,
+                            bool *respondsToCallback);
   void VisitLocation(CheckerContext &C, const Stmt *S, SVal l);
+  virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE,
+                            SVal location, SVal val);
 
 private:
   void MallocMem(CheckerContext &C, const CallExpr *CE);
+  void MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE,
+                            const OwnershipAttr* Att);
   const GRState *MallocMemAux(CheckerContext &C, const CallExpr *CE,
                               const Expr *SizeEx, SVal Init,
                               const GRState *state) {
@@ -86,8 +99,10 @@ private:
                               const GRState *state);
 
   void FreeMem(CheckerContext &C, const CallExpr *CE);
+  void FreeMemAttr(CheckerContext &C, const CallExpr *CE,
+                   const OwnershipAttr* Att);
   const GRState *FreeMemAux(CheckerContext &C, const CallExpr *CE,
-                            const GRState *state);
+                            const GRState *state, unsigned Num, bool Hold);
 
   void ReallocMem(CheckerContext &C, const CallExpr *CE);
   void CallocMem(CheckerContext &C, const CallExpr *CE);
@@ -103,7 +118,7 @@ typedef llvm::ImmutableMap<SymbolRef, RefState> RegionStateTy;
 namespace clang {
   template <>
   struct GRStateTrait<RegionState> 
-    : public GRStatePartialTrait<llvm::ImmutableMap<SymbolRef, RefState> > {
+    : public GRStatePartialTrait<RegionStateTy> {
     static void *GDMIndex() { return MallocChecker::getTag(); }
   };
 }
@@ -156,7 +171,32 @@ bool MallocChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
     return true;
   }
 
-  return false;
+  // Check all the attributes, if there are any.
+  // There can be multiple of these attributes.
+  bool rv = false;
+  if (FD->hasAttrs()) {
+    for (specific_attr_iterator<OwnershipAttr>
+                  i = FD->specific_attr_begin<OwnershipAttr>(),
+                  e = FD->specific_attr_end<OwnershipAttr>();
+         i != e; ++i) {
+      switch ((*i)->getOwnKind()) {
+      case OwnershipAttr::Returns: {
+        MallocMemReturnsAttr(C, CE, *i);
+        rv = true;
+        break;
+      }
+      case OwnershipAttr::Takes:
+      case OwnershipAttr::Holds: {
+        FreeMemAttr(C, CE, *i);
+        rv = true;
+        break;
+      }
+      default:
+        break;
+      }
+    }
+  }
+  return rv;
 }
 
 void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE) {
@@ -165,6 +205,23 @@ void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE) {
   C.addTransition(state);
 }
 
+void MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE,
+                                         const OwnershipAttr* Att) {
+  if (Att->getModule() != "malloc")
+    return;
+
+  OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
+  if (I != E) {
+    const GRState *state =
+        MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), C.getState());
+    C.addTransition(state);
+    return;
+  }
+  const GRState *state = MallocMemAux(C, CE, UnknownVal(), UndefinedVal(),
+                                        C.getState());
+  C.addTransition(state);
+}
+
 const GRState *MallocChecker::MallocMemAux(CheckerContext &C,  
                                            const CallExpr *CE,
                                            SVal Size, SVal Init,
@@ -196,25 +253,53 @@ const GRState *MallocChecker::MallocMemAux(CheckerContext &C,
 }
 
 void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) {
-  const GRState *state = FreeMemAux(C, CE, C.getState());
+  const GRState *state = FreeMemAux(C, CE, C.getState(), 0, false);
 
   if (state)
     C.addTransition(state);
 }
 
+void MallocChecker::FreeMemAttr(CheckerContext &C, const CallExpr *CE,
+                                const OwnershipAttr* Att) {
+  if (Att->getModule() != "malloc")
+    return;
+
+  for (OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
+       I != E; ++I) {
+    const GRState *state = FreeMemAux(C, CE, C.getState(), *I,
+                                      Att->getOwnKind() == OwnershipAttr::Holds);
+    if (state)
+      C.addTransition(state);
+  }
+}
+
 const GRState *MallocChecker::FreeMemAux(CheckerContext &C, const CallExpr *CE,
-                                         const GRState *state) {
-  const Expr *ArgExpr = CE->getArg(0);
+                                         const GRState *state, unsigned Num,
+                                         bool Hold) {
+  const Expr *ArgExpr = CE->getArg(Num);
   SVal ArgVal = state->getSVal(ArgExpr);
 
-  // If ptr is NULL, no operation is preformed.
-  if (ArgVal.isZeroConstant())
+  DefinedOrUnknownSVal location = cast<DefinedOrUnknownSVal>(ArgVal);
+
+  // Check for null dereferences.
+  if (!isa<Loc>(location))
     return state;
-  
+
+  // FIXME: Technically using 'Assume' here can result in a path
+  //  bifurcation.  In such cases we need to return two states, not just one.
+  const GRState *notNullState, *nullState;
+  llvm::tie(notNullState, nullState) = state->Assume(location);
+
+  // The explicit NULL case, no operation is performed.
+  if (nullState && !notNullState)
+    return nullState;
+
+  assert(notNullState);
+
   // Unknown values could easily be okay
   // Undefined values are handled elsewhere
   if (ArgVal.isUnknownOrUndef())
-    return state;
+    return notNullState;
 
   const MemRegion *R = ArgVal.getAsRegion();
   
@@ -253,24 +338,23 @@ const GRState *MallocChecker::FreeMemAux(CheckerContext &C, const CallExpr *CE,
   // Various cases could lead to non-symbol values here.
   // For now, ignore them.
   if (!SR)
-    return state;
+    return notNullState;
 
   SymbolRef Sym = SR->getSymbol();
-  
   const RefState *RS = state->get<RegionState>(Sym);
 
   // If the symbol has not been tracked, return. This is possible when free() is
   // called on a pointer that does not get its pointee directly from malloc(). 
   // Full support of this requires inter-procedural analysis.
   if (!RS)
-    return state;
+    return notNullState;
 
   // Check double free.
   if (RS->isReleased()) {
-    ExplodedNode *N = C.GenerateSink();
-    if (N) {
+    if (ExplodedNode *N = C.GenerateSink()) {
       if (!BT_DoubleFree)
-        BT_DoubleFree = new BuiltinBug("Double free",
+        BT_DoubleFree
+          = new BuiltinBug("Double free",
                          "Try to free a memory block that has been released");
       // FIXME: should find where it's freed last time.
       BugReport *R = new BugReport(*BT_DoubleFree, 
@@ -281,7 +365,9 @@ const GRState *MallocChecker::FreeMemAux(CheckerContext &C, const CallExpr *CE,
   }
 
   // Normal free.
-  return state->set<RegionState>(Sym, RefState::getReleased(CE));
+  if (Hold)
+    return notNullState->set<RegionState>(Sym, RefState::getRelinquished(CE));
+  return notNullState->set<RegionState>(Sym, RefState::getReleased(CE));
 }
 
 bool MallocChecker::SummarizeValue(llvm::raw_ostream& os, SVal V) {
@@ -376,8 +462,7 @@ bool MallocChecker::SummarizeRegion(llvm::raw_ostream& os,
 
 void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal,
                                   SourceRange range) {
-  ExplodedNode *N = C.GenerateSink();
-  if (N) {
+  if (ExplodedNode *N = C.GenerateSink()) {
     if (!BT_BadFree)
       BT_BadFree = new BuiltinBug("Bad free");
     
@@ -446,13 +531,13 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) {
                                       ValMgr.makeIntValWithPtrWidth(0, false));
 
     if (const GRState *stateSizeZero = stateNotEqual->Assume(SizeZero, true)) {
-      const GRState *stateFree = FreeMemAux(C, CE, stateSizeZero);
+      const GRState *stateFree = FreeMemAux(C, CE, stateSizeZero, 0, false);
       if (stateFree)
         C.addTransition(stateFree->BindExpr(CE, UndefinedVal(), true));
     }
 
     if (const GRState *stateSizeNotZero=stateNotEqual->Assume(SizeZero,false)) {
-      const GRState *stateFree = FreeMemAux(C, CE, stateSizeNotZero);
+      const GRState *stateFree = FreeMemAux(C, CE, stateSizeNotZero, 0, false);
       if (stateFree) {
         // FIXME: We should copy the content of the original buffer.
         const GRState *stateRealloc = MallocMemAux(C, CE, CE->getArg(1), 
@@ -471,7 +556,7 @@ void MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE) {
 
   SVal Count = state->getSVal(CE->getArg(0));
   SVal EleSize = state->getSVal(CE->getArg(1));
-  SVal TotalSize = SVator.EvalBinOp(state, BinaryOperator::Mul, Count, EleSize,
+  SVal TotalSize = SVator.EvalBinOp(state, BO_Mul, Count, EleSize,
                                     ValMgr.getContext().getSizeType());
   
   SVal Zero = ValMgr.makeZeroVal(ValMgr.getContext().CharTy);
@@ -481,36 +566,42 @@ void MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE) {
 }
 
 void MallocChecker::EvalDeadSymbols(CheckerContext &C,SymbolReaper &SymReaper) {
-  for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
-         E = SymReaper.dead_end(); I != E; ++I) {
-    SymbolRef Sym = *I;
-    const GRState *state = C.getState();
-    const RefState *RS = state->get<RegionState>(Sym);
-    if (!RS)
-      return;
-
-    if (RS->isAllocated()) {
-      ExplodedNode *N = C.GenerateSink();
-      if (N) {
-        if (!BT_Leak)
-          BT_Leak = new BuiltinBug("Memory leak",
+  if (!SymReaper.hasDeadSymbols())
+    return;
+
+  const GRState *state = C.getState();
+  RegionStateTy RS = state->get<RegionState>();
+  RegionStateTy::Factory &F = state->get_context<RegionState>();
+
+  for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
+    if (SymReaper.isDead(I->first)) {
+      if (I->second.isAllocated()) {
+        if (ExplodedNode *N = C.GenerateNode()) {
+          if (!BT_Leak)
+            BT_Leak = new BuiltinBug("Memory leak",
                      "Allocated memory never released. Potential memory leak.");
-        // FIXME: where it is allocated.
-        BugReport *R = new BugReport(*BT_Leak, BT_Leak->getDescription(), N);
-        C.EmitReport(R);
+          // FIXME: where it is allocated.
+          BugReport *R = new BugReport(*BT_Leak, BT_Leak->getDescription(), N);
+          C.EmitReport(R);
+        }
       }
+
+      // Remove the dead symbol from the map.
+      RS = F.Remove(RS, I->first);
     }
   }
+
+  state = state->set<RegionState>(RS);
+  C.GenerateNode(state);
 }
 
 void MallocChecker::EvalEndPath(GREndPathNodeBuilder &B, void *tag,
                                 GRExprEngine &Eng) {
   SaveAndRestore<bool> OldHasGen(B.HasGeneratedNode);
   const GRState *state = B.getState();
-  typedef llvm::ImmutableMap<SymbolRef, RefState> SymMap;
-  SymMap M = state->get<RegionState>();
+  RegionStateTy M = state->get<RegionState>();
 
-  for (SymMap::iterator I = M.begin(), E = M.end(); I != E; ++I) {
+  for (RegionStateTy::iterator I = M.begin(), E = M.end(); I != E; ++I) {
     RefState RS = I->second;
     if (RS.isAllocated()) {
       ExplodedNode *N = B.generateNode(state, tag, B.getPredecessor());
@@ -549,7 +640,8 @@ void MallocChecker::PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S) {
 }
 
 const GRState *MallocChecker::EvalAssume(const GRState *state, SVal Cond, 
-                                         bool Assumption) {
+                                         bool Assumption,
+                                         bool * /* respondsToCallback */) {
   // If a symblic region is assumed to NULL, set its state to AllocateFailed.
   // FIXME: should also check symbols assumed to non-null.
 
@@ -568,9 +660,8 @@ void MallocChecker::VisitLocation(CheckerContext &C, const Stmt *S, SVal l) {
   SymbolRef Sym = l.getLocSymbolInBase();
   if (Sym) {
     const RefState *RS = C.getState()->get<RegionState>(Sym);
-    if (RS)
-      if (RS->isReleased()) {
-        ExplodedNode *N = C.GenerateSink();
+    if (RS && RS->isReleased()) {
+      if (ExplodedNode *N = C.GenerateNode()) {
         if (!BT_UseFree)
           BT_UseFree = new BuiltinBug("Use dynamically allocated memory after"
                                       " it is freed.");
@@ -579,5 +670,67 @@ void MallocChecker::VisitLocation(CheckerContext &C, const Stmt *S, SVal l) {
                                      N);
         C.EmitReport(R);
       }
+    }
+  }
+}
+
+void MallocChecker::PreVisitBind(CheckerContext &C,
+                                 const Stmt *StoreE,
+                                 SVal location,
+                                 SVal val) {
+  // The PreVisitBind implements the same algorithm as already used by the 
+  // Objective C ownership checker: if the pointer escaped from this scope by 
+  // assignment, let it go.  However, assigning to fields of a stack-storage 
+  // structure does not transfer ownership.
+
+  const GRState *state = C.getState();
+  DefinedOrUnknownSVal l = cast<DefinedOrUnknownSVal>(location);
+
+  // Check for null dereferences.
+  if (!isa<Loc>(l))
+    return;
+
+  // Before checking if the state is null, check if 'val' has a RefState.
+  // Only then should we check for null and bifurcate the state.
+  SymbolRef Sym = val.getLocSymbolInBase();
+  if (Sym) {
+    if (const RefState *RS = state->get<RegionState>(Sym)) {
+      // If ptr is NULL, no operation is performed.
+      const GRState *notNullState, *nullState;
+      llvm::tie(notNullState, nullState) = state->Assume(l);
+
+      // Generate a transition for 'nullState' to record the assumption
+      // that the state was null.
+      if (nullState)
+        C.addTransition(nullState);
+
+      if (!notNullState)
+        return;
+
+      if (RS->isAllocated()) {
+        // Something we presently own is being assigned somewhere.
+        const MemRegion *AR = location.getAsRegion();
+        if (!AR)
+          return;
+        AR = AR->StripCasts()->getBaseRegion();
+        do {
+          // If it is on the stack, we still own it.
+          if (AR->hasStackNonParametersStorage())
+            break;
+
+          // If the state can't represent this binding, we still own it.
+          if (notNullState == (notNullState->bindLoc(cast<Loc>(location),
+                                                     UnknownVal())))
+            break;
+
+          // We no longer own this pointer.
+          notNullState =
+            notNullState->set<RegionState>(Sym,
+                                           RefState::getRelinquished(StoreE));
+        }
+        while (false);
+      }
+      C.addTransition(notNullState);
+    }
   }
 }
diff --git a/lib/Checker/MemRegion.cpp b/lib/Checker/MemRegion.cpp
index 9cfeb7a..3f706e1 100644
--- a/lib/Checker/MemRegion.cpp
+++ b/lib/Checker/MemRegion.cpp
@@ -18,6 +18,7 @@
 #include "clang/Analysis/AnalysisContext.h"
 #include "clang/Analysis/Support/BumpVector.h"
 #include "clang/AST/CharUnits.h"
+#include "clang/AST/RecordLayout.h"
 #include "llvm/Support/raw_ostream.h"
 
 using namespace clang;
@@ -177,7 +178,7 @@ const StackFrameContext *VarRegion::getStackFrame() const {
 
 DefinedOrUnknownSVal DeclRegion::getExtent(ValueManager& ValMgr) const {
   ASTContext& Ctx = ValMgr.getContext();
-  QualType T = getDesugaredValueType(Ctx);
+  QualType T = getDesugaredValueType();
 
   if (isa<VariableArrayType>(T))
     return nonloc::SymbolVal(ValMgr.getSymbolManager().getExtentSymbol(this));
@@ -195,8 +196,7 @@ DefinedOrUnknownSVal FieldRegion::getExtent(ValueManager& ValMgr) const {
   // A zero-length array at the end of a struct often stands for dynamically-
   // allocated extra memory.
   if (Extent.isZeroConstant()) {
-    ASTContext& Ctx = ValMgr.getContext();
-    QualType T = getDesugaredValueType(Ctx);
+    QualType T = getDesugaredValueType();
 
     if (isa<ConstantArrayType>(T))
       return UnknownVal();
@@ -785,7 +785,7 @@ static bool IsCompleteType(ASTContext &Ctx, QualType Ty) {
   return true;
 }
 
-RegionRawOffset ElementRegion::getAsRawOffset() const {
+RegionRawOffset ElementRegion::getAsArrayOffset() const {
   CharUnits offset = CharUnits::Zero();
   const ElementRegion *ER = this;
   const MemRegion *superR = NULL;
@@ -827,6 +827,67 @@ RegionRawOffset ElementRegion::getAsRawOffset() const {
   return RegionRawOffset(superR, offset.getQuantity());
 }
 
+RegionOffset MemRegion::getAsOffset() const {
+  const MemRegion *R = this;
+  int64_t Offset = 0;
+
+  while (1) {
+    switch (R->getKind()) {
+    default:
+      return RegionOffset(0);
+    case SymbolicRegionKind:
+    case AllocaRegionKind:
+    case CompoundLiteralRegionKind:
+    case CXXThisRegionKind:
+    case StringRegionKind:
+    case VarRegionKind:
+    case CXXObjectRegionKind:
+      goto Finish;
+    case ElementRegionKind: {
+      const ElementRegion *ER = cast<ElementRegion>(R);
+      QualType EleTy = ER->getValueType();
+
+      if (!IsCompleteType(getContext(), EleTy))
+        return RegionOffset(0);
+
+      SVal Index = ER->getIndex();
+      if (const nonloc::ConcreteInt *CI=dyn_cast<nonloc::ConcreteInt>(&Index)) {
+        int64_t i = CI->getValue().getSExtValue();
+        CharUnits Size = getContext().getTypeSizeInChars(EleTy);
+        Offset += i * Size.getQuantity() * 8;
+      } else {
+        // We cannot compute offset for non-concrete index.
+        return RegionOffset(0);
+      }
+      R = ER->getSuperRegion();
+      break;
+    }
+    case FieldRegionKind: {
+      const FieldRegion *FR = cast<FieldRegion>(R);
+      const RecordDecl *RD = FR->getDecl()->getParent();
+      if (!RD->isDefinition())
+        // We cannot compute offset for incomplete type.
+        return RegionOffset(0);
+      // Get the field number.
+      unsigned idx = 0;
+      for (RecordDecl::field_iterator FI = RD->field_begin(), 
+             FE = RD->field_end(); FI != FE; ++FI, ++idx)
+        if (FR->getDecl() == *FI)
+          break;
+
+      const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
+      // This is offset in bits.
+      Offset += Layout.getFieldOffset(idx);
+      R = FR->getSuperRegion();
+      break;
+    }
+    }
+  }
+
+ Finish:
+  return RegionOffset(R, Offset);
+}
+
 //===----------------------------------------------------------------------===//
 // BlockDataRegion
 //===----------------------------------------------------------------------===//
diff --git a/lib/Checker/OSAtomicChecker.cpp b/lib/Checker/OSAtomicChecker.cpp
index 1ea1bd9..02de0a8 100644
--- a/lib/Checker/OSAtomicChecker.cpp
+++ b/lib/Checker/OSAtomicChecker.cpp
@@ -110,9 +110,9 @@ bool OSAtomicChecker::EvalOSAtomicCompareAndSwap(CheckerContext &C,
   QualType LoadTy;
   if (const TypedRegion *TR =
       dyn_cast_or_null<TypedRegion>(location.getAsRegion())) {
-    LoadTy = TR->getValueType(Ctx);
+    LoadTy = TR->getValueType();
   }
-  Engine.EvalLoad(Tmp, const_cast<Expr *>(theValueExpr), C.getPredecessor(), 
+  Engine.EvalLoad(Tmp, theValueExpr, C.getPredecessor(), 
                   state, location, OSAtomicLoadTag, LoadTy);
 
   if (Tmp.empty()) {
@@ -158,10 +158,10 @@ bool OSAtomicChecker::EvalOSAtomicCompareAndSwap(CheckerContext &C,
       // Handle implicit value casts.
       if (const TypedRegion *R =
           dyn_cast_or_null<TypedRegion>(location.getAsRegion())) {
-        val = SVator.EvalCast(val,R->getValueType(Ctx),newValueExpr->getType());
+        val = SVator.EvalCast(val,R->getValueType(), newValueExpr->getType());
       }
 
-      Engine.EvalStore(TmpStore, NULL, const_cast<Expr *>(theValueExpr), N, 
+      Engine.EvalStore(TmpStore, NULL, theValueExpr, N, 
                        stateEqual, location, val, OSAtomicStoreTag);
 
       if (TmpStore.empty()) {
diff --git a/lib/Checker/PointerArithChecker.cpp b/lib/Checker/PointerArithChecker.cpp
index ed60c42..cbac423 100644
--- a/lib/Checker/PointerArithChecker.cpp
+++ b/lib/Checker/PointerArithChecker.cpp
@@ -36,8 +36,7 @@ void *PointerArithChecker::getTag() {
 
 void PointerArithChecker::PreVisitBinaryOperator(CheckerContext &C,
                                                  const BinaryOperator *B) {
-  if (B->getOpcode() != BinaryOperator::Sub &&
-      B->getOpcode() != BinaryOperator::Add)
+  if (B->getOpcode() != BO_Sub && B->getOpcode() != BO_Add)
     return;
 
   const GRState *state = C.getState();
diff --git a/lib/Checker/PointerSubChecker.cpp b/lib/Checker/PointerSubChecker.cpp
index bc0fd24..d64b6ae 100644
--- a/lib/Checker/PointerSubChecker.cpp
+++ b/lib/Checker/PointerSubChecker.cpp
@@ -39,7 +39,7 @@ void PointerSubChecker::PreVisitBinaryOperator(CheckerContext &C,
                                                const BinaryOperator *B) {
   // When doing pointer subtraction, if the two pointers do not point to the
   // same memory chunk, emit a warning.
-  if (B->getOpcode() != BinaryOperator::Sub)
+  if (B->getOpcode() != BO_Sub)
     return;
 
   const GRState *state = C.getState();
diff --git a/lib/Checker/RangeConstraintManager.cpp b/lib/Checker/RangeConstraintManager.cpp
index 2a35d32..697694e 100644
--- a/lib/Checker/RangeConstraintManager.cpp
+++ b/lib/Checker/RangeConstraintManager.cpp
@@ -83,7 +83,6 @@ public:
   typedef PrimRangeSet::iterator iterator;
 
   RangeSet(PrimRangeSet RS) : ranges(RS) {}
-  RangeSet(Factory& F) : ranges(F.GetEmptySet()) {}
 
   iterator begin() const { return ranges.begin(); }
   iterator end() const { return ranges.end(); }
diff --git a/lib/Checker/RegionStore.cpp b/lib/Checker/RegionStore.cpp
index 74a7fee..1a3eded 100644
--- a/lib/Checker/RegionStore.cpp
+++ b/lib/Checker/RegionStore.cpp
@@ -44,10 +44,9 @@ private:
   uint64_t Offset;
 
   explicit BindingKey(const MemRegion *r, uint64_t offset, Kind k)
-    : P(r, (unsigned) k), Offset(offset) { assert(r); }
+    : P(r, (unsigned) k), Offset(offset) {}
 public:
 
-  bool isDefault() const { return P.getInt() == Default; }
   bool isDirect() const { return P.getInt() == Direct; }
 
   const MemRegion *getRegion() const { return P.getPointer(); }
@@ -72,9 +71,26 @@ public:
     return P.getOpaqueValue() == X.P.getOpaqueValue() &&
            Offset == X.Offset;
   }
+
+  bool isValid() const {
+    return getRegion() != NULL;
+  }
 };
 } // end anonymous namespace
 
+BindingKey BindingKey::Make(const MemRegion *R, Kind k) {
+  if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
+    const RegionRawOffset &O = ER->getAsArrayOffset();
+
+    // FIXME: There are some ElementRegions for which we cannot compute
+    // raw offsets yet, including regions with symbolic offsets. These will be
+    // ignored by the store.
+    return BindingKey(O.getRegion(), O.getByteOffset(), k);
+  }
+
+  return BindingKey(R, 0, k);
+}
+
 namespace llvm {
   static inline
   llvm::raw_ostream& operator<<(llvm::raw_ostream& os, BindingKey K) {
@@ -101,35 +117,20 @@ struct maximal_features_tag {};
 
 class RegionStoreFeatures {
   bool SupportsFields;
-  bool SupportsRemaining;
-
 public:
   RegionStoreFeatures(minimal_features_tag) :
-    SupportsFields(false), SupportsRemaining(false) {}
+    SupportsFields(false) {}
 
   RegionStoreFeatures(maximal_features_tag) :
-    SupportsFields(true), SupportsRemaining(false) {}
+    SupportsFields(true) {}
 
   void enableFields(bool t) { SupportsFields = t; }
 
   bool supportsFields() const { return SupportsFields; }
-  bool supportsRemaining() const { return SupportsRemaining; }
 };
 }
 
 //===----------------------------------------------------------------------===//
-// Utility functions.
-//===----------------------------------------------------------------------===//
-
-static bool IsAnyPointerOrIntptr(QualType ty, ASTContext &Ctx) {
-  if (ty->isAnyPointerType())
-    return true;
-
-  return ty->isIntegerType() && ty->isScalarType() &&
-         Ctx.getTypeSize(ty) == Ctx.getTypeSize(Ctx.VoidPtrTy);
-}
-
-//===----------------------------------------------------------------------===//
 // Main RegionStore logic.
 //===----------------------------------------------------------------------===//
 
@@ -180,6 +181,14 @@ public:
   }
 };
 
+void
+RegionStoreSubRegionMap::process(llvm::SmallVectorImpl<const SubRegion*> &WL,
+                                 const SubRegion *R) {
+  const MemRegion *superR = R->getSuperRegion();
+  if (add(superR, R))
+    if (const SubRegion *sr = dyn_cast<SubRegion>(superR))
+      WL.push_back(sr);
+}
 
 class RegionStoreManager : public StoreManager {
   const RegionStoreFeatures Features;
@@ -197,7 +206,6 @@ public:
 
   RegionStoreSubRegionMap *getRegionStoreSubRegionMap(Store store);
 
-  Optional<SVal> getBinding(RegionBindings B, const MemRegion *R);
   Optional<SVal> getDirectBinding(RegionBindings B, const MemRegion *R);
   /// getDefaultBinding - Returns an SVal* representing an optional default
   ///  binding associated with a region and its subregions.
@@ -226,18 +234,13 @@ public:
   // Binding values to regions.
   //===-------------------------------------------------------------------===//
 
-  Store InvalidateRegion(Store store, const MemRegion *R, const Expr *E,
-                         unsigned Count, InvalidatedSymbols *IS) {
-    return RegionStoreManager::InvalidateRegions(store, &R, &R+1, E, Count, IS,
-                                                 false);
-  }
-
   Store InvalidateRegions(Store store,
                           const MemRegion * const *Begin,
                           const MemRegion * const *End,
                           const Expr *E, unsigned Count,
                           InvalidatedSymbols *IS,
-                          bool invalidateGlobals);
+                          bool invalidateGlobals,
+                          InvalidatedRegions *Regions);
 
 public:   // Made public for helper classes.
 
@@ -260,8 +263,6 @@ public:   // Made public for helper classes.
     return Remove(Remove(B, R, BindingKey::Direct), R, BindingKey::Default);
   }
 
-  Store Remove(Store store, BindingKey K);
-
 public: // Part of public interface to class.
 
   Store Bind(Store store, Loc LV, SVal V);
@@ -289,7 +290,7 @@ public: // Part of public interface to class.
   Store BindArray(Store store, const TypedRegion* R, SVal V);
 
   /// KillStruct - Set the entire struct to unknown.
-  Store KillStruct(Store store, const TypedRegion* R);
+  Store KillStruct(Store store, const TypedRegion* R, SVal DefaultVal);
 
   Store Remove(Store store, Loc LV);
 
@@ -352,13 +353,11 @@ public: // Part of public interface to class.
 
   /// RemoveDeadBindings - Scans the RegionStore of 'state' for dead values.
   ///  It returns a new Store with these values removed.
-  const GRState *RemoveDeadBindings(GRState &state, 
-                                    const StackFrameContext *LCtx,
-                                    SymbolReaper& SymReaper,
+  Store RemoveDeadBindings(Store store, const StackFrameContext *LCtx,
+                           SymbolReaper& SymReaper,
                           llvm::SmallVectorImpl<const MemRegion*>& RegionRoots);
 
-  const GRState *EnterStackFrame(const GRState *state,
-                                 const StackFrameContext *frame);
+  Store EnterStackFrame(const GRState *state, const StackFrameContext *frame);
 
   //===------------------------------------------------------------------===//
   // Region "extents".
@@ -392,9 +391,6 @@ public: // Part of public interface to class.
       }
     }
   }
-
-  // FIXME: Remove.
-  ASTContext& getContext() { return StateMgr.getContext(); }
 };
 
 } // end anonymous namespace
@@ -414,14 +410,6 @@ StoreManager *clang::CreateFieldsOnlyRegionStoreManager(GRStateManager &StMgr) {
   return new RegionStoreManager(StMgr, F);
 }
 
-void
-RegionStoreSubRegionMap::process(llvm::SmallVectorImpl<const SubRegion*> &WL,
-                                 const SubRegion *R) {
-  const MemRegion *superR = R->getSuperRegion();
-  if (add(superR, R))
-    if (const SubRegion *sr = dyn_cast<SubRegion>(superR))
-      WL.push_back(sr);
-}
 
 RegionStoreSubRegionMap*
 RegionStoreManager::getRegionStoreSubRegionMap(Store store) {
@@ -579,14 +567,16 @@ class InvalidateRegionsWorker : public ClusterAnalysis<InvalidateRegionsWorker>
   const Expr *Ex;
   unsigned Count;
   StoreManager::InvalidatedSymbols *IS;
+  StoreManager::InvalidatedRegions *Regions;
 public:
   InvalidateRegionsWorker(RegionStoreManager &rm,
                           GRStateManager &stateMgr,
                           RegionBindings b,
                           const Expr *ex, unsigned count,
-                          StoreManager::InvalidatedSymbols *is)
+                          StoreManager::InvalidatedSymbols *is,
+                          StoreManager::InvalidatedRegions *r)
     : ClusterAnalysis<InvalidateRegionsWorker>(rm, stateMgr, b),
-      Ex(ex), Count(count), IS(is) {}
+      Ex(ex), Count(count), IS(is), Regions(r) {}
 
   void VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E);
   void VisitBaseRegion(const MemRegion *baseR);
@@ -657,6 +647,10 @@ void InvalidateRegionsWorker::VisitBaseRegion(const MemRegion *baseR) {
     return;
   }
 
+  // Otherwise, we have a normal data region. Record that we touched the region.
+  if (Regions)
+    Regions->push_back(baseR);
+
   if (isa<AllocaRegion>(baseR) || isa<SymbolicRegion>(baseR)) {
     // Invalidate the region by setting its default value to
     // conjured symbol. The type of the symbol is irrelavant.
@@ -670,19 +664,12 @@ void InvalidateRegionsWorker::VisitBaseRegion(const MemRegion *baseR) {
     return;
 
   const TypedRegion *TR = cast<TypedRegion>(baseR);
-  QualType T = TR->getValueType(Ctx);
+  QualType T = TR->getValueType();
 
     // Invalidate the binding.
-  if (const RecordType *RT = T->getAsStructureType()) {
-    const RecordDecl *RD = RT->getDecl()->getDefinition();
-      // No record definition.  There is nothing we can do.
-    if (!RD) {
-      B = RM.Remove(B, baseR);
-      return;
-    }
-
-      // Invalidate the region by setting its default value to
-      // conjured symbol. The type of the symbol is irrelavant.
+  if (T->isStructureType()) {
+    // Invalidate the region by setting its default value to
+    // conjured symbol. The type of the symbol is irrelavant.
     DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(baseR, Ex, Ctx.IntTy,
                                                          Count);
     B = RM.Add(B, baseR, BindingKey::Default, V);
@@ -707,10 +694,11 @@ Store RegionStoreManager::InvalidateRegions(Store store,
                                             const MemRegion * const *E,
                                             const Expr *Ex, unsigned Count,
                                             InvalidatedSymbols *IS,
-                                            bool invalidateGlobals) {
+                                            bool invalidateGlobals,
+                                            InvalidatedRegions *Regions) {
   InvalidateRegionsWorker W(*this, StateMgr,
                             RegionStoreManager::GetRegionBindings(store),
-                            Ex, Count, IS);
+                            Ex, Count, IS, Regions);
 
   // Scan the bindings and generate the clusters.
   W.GenerateClusters(invalidateGlobals);
@@ -733,6 +721,11 @@ Store RegionStoreManager::InvalidateRegions(Store store,
                                   /* symbol type, doesn't matter */ Ctx.IntTy,
                                   Count);
     B = Add(B, BindingKey::Make(GS, BindingKey::Default), V);
+
+    // Even if there are no bindings in the global scope, we still need to
+    // record that we touched it.
+    if (Regions)
+      Regions->push_back(GS);
   }
 
   return B.getRoot();
@@ -752,7 +745,7 @@ DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state,
     return UnknownVal();
 
   CharUnits RegionSize = CharUnits::fromQuantity(SizeInt->getSExtValue());
-  CharUnits EleSize = getContext().getTypeSizeInChars(EleTy);
+  CharUnits EleSize = Ctx.getTypeSizeInChars(EleTy);
 
   // If a variable is reinterpreted as a type that doesn't fit into a larger
   // type evenly, round it down.
@@ -781,13 +774,12 @@ SVal RegionStoreManager::ArrayToPointer(Loc Array) {
     return UnknownVal();
 
   // Strip off typedefs from the ArrayRegion's ValueType.
-  QualType T = ArrayR->getValueType(getContext()).getDesugaredType();
+  QualType T = ArrayR->getValueType().getDesugaredType();
   ArrayType *AT = cast<ArrayType>(T);
   T = AT->getElementType();
 
   SVal ZeroIdx = ValMgr.makeZeroArrayIndex();
-  return loc::MemRegionVal(MRMgr.getElementRegion(T, ZeroIdx, ArrayR,
-                                                  getContext()));
+  return loc::MemRegionVal(MRMgr.getElementRegion(T, ZeroIdx, ArrayR, Ctx));
 }
 
 //===----------------------------------------------------------------------===//
@@ -806,8 +798,8 @@ SVal RegionStoreManager::EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R,
     default:
       // Handle it normally.
       break;
-    case BinaryOperator::Add:
-    case BinaryOperator::Sub:
+    case BO_Add:
+    case BO_Sub:
       // FIXME: does this need to be casted to match resultTy?
       return L;
     }
@@ -820,7 +812,7 @@ SVal RegionStoreManager::EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R,
     case MemRegion::SymbolicRegionKind: {
       const SymbolicRegion *SR = cast<SymbolicRegion>(MR);
       SymbolRef Sym = SR->getSymbol();
-      QualType T = Sym->getType(getContext());
+      QualType T = Sym->getType(Ctx);
       QualType EleTy;
 
       if (const PointerType *PT = T->getAs<PointerType>())
@@ -829,14 +821,14 @@ SVal RegionStoreManager::EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R,
         EleTy = T->getAs<ObjCObjectPointerType>()->getPointeeType();
 
       SVal ZeroIdx = ValMgr.makeZeroArrayIndex();
-      ER = MRMgr.getElementRegion(EleTy, ZeroIdx, SR, getContext());
+      ER = MRMgr.getElementRegion(EleTy, ZeroIdx, SR, Ctx);
       break;
     }
     case MemRegion::AllocaRegionKind: {
       const AllocaRegion *AR = cast<AllocaRegion>(MR);
-      QualType EleTy = getContext().CharTy; // Create an ElementRegion of bytes.
+      QualType EleTy = Ctx.CharTy; // Create an ElementRegion of bytes.
       SVal ZeroIdx = ValMgr.makeZeroArrayIndex();
-      ER = MRMgr.getElementRegion(EleTy, ZeroIdx, AR, getContext());
+      ER = MRMgr.getElementRegion(EleTy, ZeroIdx, AR, Ctx);
       break;
     }
 
@@ -891,13 +883,13 @@ SVal RegionStoreManager::EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R,
                 cast<nonloc::ConcreteInt>(ValMgr.convertToArrayIndex(*Offset)));
       const MemRegion* NewER =
         MRMgr.getElementRegion(ER->getElementType(), NewIdx,
-                               ER->getSuperRegion(), getContext());
+                               ER->getSuperRegion(), Ctx);
       return ValMgr.makeLoc(NewER);
     }
     if (0 == Base->getValue()) {
       const MemRegion* NewER =
         MRMgr.getElementRegion(ER->getElementType(), R,
-                               ER->getSuperRegion(), getContext());
+                               ER->getSuperRegion(), Ctx);
       return ValMgr.makeLoc(NewER);
     }
   }
@@ -922,7 +914,7 @@ Optional<SVal> RegionStoreManager::getDefaultBinding(RegionBindings B,
                                                      const MemRegion *R) {
   if (R->isBoundable())
     if (const TypedRegion *TR = dyn_cast<TypedRegion>(R))
-      if (TR->getValueType(getContext())->isUnionType())
+      if (TR->getValueType()->isUnionType())
         return UnknownVal();
 
   if (const SVal *V = Lookup(B, R, BindingKey::Default))
@@ -931,38 +923,6 @@ Optional<SVal> RegionStoreManager::getDefaultBinding(RegionBindings B,
   return Optional<SVal>();
 }
 
-Optional<SVal> RegionStoreManager::getBinding(RegionBindings B,
-                                              const MemRegion *R) {
-
-  if (const Optional<SVal> &V = getDirectBinding(B, R))
-    return V;
-
-  return getDefaultBinding(B, R);
-}
-
-static bool IsReinterpreted(QualType RTy, QualType UsedTy, ASTContext &Ctx) {
-  RTy = Ctx.getCanonicalType(RTy);
-  UsedTy = Ctx.getCanonicalType(UsedTy);
-
-  if (RTy == UsedTy)
-    return false;
-
-
-  // Recursively check the types.  We basically want to see if a pointer value
-  // is ever reinterpreted as a non-pointer, e.g. void** and intptr_t*
-  // represents a reinterpretation.
-  if (Loc::IsLocType(RTy) && Loc::IsLocType(UsedTy)) {
-    const PointerType *PRTy = RTy->getAs<PointerType>();
-    const PointerType *PUsedTy = UsedTy->getAs<PointerType>();
-
-    return PUsedTy && PRTy &&
-           IsReinterpreted(PRTy->getPointeeType(),
-                           PUsedTy->getPointeeType(), Ctx);
-  }
-
-  return true;
-}
-
 SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) {
   assert(!isa<UnknownVal>(L) && "location unknown");
   assert(!isa<UndefinedVal>(L) && "location undefined");
@@ -977,7 +937,7 @@ SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) {
   if (isa<AllocaRegion>(MR) || isa<SymbolicRegion>(MR)) {
     if (T.isNull()) {
       const SymbolicRegion *SR = cast<SymbolicRegion>(MR);
-      T = SR->getSymbol()->getType(getContext());
+      T = SR->getSymbol()->getType(Ctx);
     }
     MR = GetElementZeroRegion(MR, T);
   }
@@ -990,7 +950,7 @@ SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) {
   // FIXME: Perhaps this method should just take a 'const MemRegion*' argument
   //  instead of 'Loc', and have the other Loc cases handled at a higher level.
   const TypedRegion *R = cast<TypedRegion>(MR);
-  QualType RTy = R->getValueType(getContext());
+  QualType RTy = R->getValueType();
 
   // FIXME: We should eventually handle funny addressing.  e.g.:
   //
@@ -1001,17 +961,6 @@ SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) {
   //
   // Such funny addressing will occur due to layering of regions.
 
-#if 0
-  ASTContext &Ctx = getContext();
-  if (!T.isNull() && IsReinterpreted(RTy, T, Ctx)) {
-    SVal ZeroIdx = ValMgr.makeZeroArrayIndex();
-    R = MRMgr.getElementRegion(T, ZeroIdx, R, Ctx);
-    RTy = T;
-    assert(Ctx.getCanonicalType(RTy) ==
-           Ctx.getCanonicalType(R->getValueType(Ctx)));
-  }
-#endif
-
   if (RTy->isStructureOrClassType())
     return RetrieveStruct(store, R);
 
@@ -1121,8 +1070,7 @@ SVal RegionStoreManager::RetrieveElement(Store store,
   if (const StringRegion *StrR=dyn_cast<StringRegion>(superR)) {
     // FIXME: Handle loads from strings where the literal is treated as
     // an integer, e.g., *((unsigned int*)"hello")
-    ASTContext &Ctx = getContext();
-    QualType T = Ctx.getAsArrayType(StrR->getValueType(Ctx))->getElementType();
+    QualType T = Ctx.getAsArrayType(StrR->getValueType())->getElementType();
     if (T != Ctx.getCanonicalType(R->getElementType()))
       return UnknownVal();
 
@@ -1131,16 +1079,18 @@ SVal RegionStoreManager::RetrieveElement(Store store,
     if (nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&Idx)) {
       int64_t i = CI->getValue().getSExtValue();
       int64_t byteLength = Str->getByteLength();
-      if (i > byteLength) {
-        // Buffer overflow checking in GRExprEngine should handle this case,
-        // but we shouldn't rely on it to not overflow here if that checking
-        // is disabled.
-        return UnknownVal();
-      }
-      char c = (i == byteLength) ? '\0' : Str->getStrData()[i];
+      // Technically, only i == byteLength is guaranteed to be null.
+      // However, such overflows should be caught before reaching this point;
+      // the only time such an access would be made is if a string literal was
+      // used to initialize a larger array.
+      char c = (i >= byteLength) ? '\0' : Str->getString()[i];
       return ValMgr.makeIntVal(c, T);
     }
   }
+  
+  // Check for loads from a code text region.  For such loads, just give up.
+  if (isa<CodeTextRegion>(superR))
+    return UnknownVal();
 
   // Handle the case where we are indexing into a larger scalar object.
   // For example, this handles:
@@ -1148,9 +1098,9 @@ SVal RegionStoreManager::RetrieveElement(Store store,
   //   char *y = &x;
   //   return *y;
   // FIXME: This is a hack, and doesn't do anything really intelligent yet.
-  const RegionRawOffset &O = R->getAsRawOffset();
+  const RegionRawOffset &O = R->getAsArrayOffset();
   if (const TypedRegion *baseR = dyn_cast_or_null<TypedRegion>(O.getRegion())) {
-    QualType baseT = baseR->getValueType(Ctx);
+    QualType baseT = baseR->getValueType();
     if (baseT->isScalarType()) {
       QualType elemT = R->getElementType();
       if (elemT->isScalarType()) {
@@ -1180,7 +1130,7 @@ SVal RegionStoreManager::RetrieveField(Store store,
   if (const Optional<SVal> &V = getDirectBinding(B, R))
     return *V;
 
-  QualType Ty = R->getValueType(getContext());
+  QualType Ty = R->getValueType();
   return RetrieveFieldOrElementCommon(store, R, Ty, R->getSuperRegion());
 }
 
@@ -1243,13 +1193,18 @@ SVal RegionStoreManager::RetrieveFieldOrElementCommon(Store store,
   }
 
   if (R->hasStackNonParametersStorage()) {
-    if (isa<ElementRegion>(R)) {
+    if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
       // Currently we don't reason specially about Clang-style vectors.  Check
       // if superR is a vector and if so return Unknown.
       if (const TypedRegion *typedSuperR = dyn_cast<TypedRegion>(superR)) {
-        if (typedSuperR->getValueType(getContext())->isVectorType())
+        if (typedSuperR->getValueType()->isVectorType())
           return UnknownVal();
       }
+      
+      // FIXME: We also need to take ElementRegions with symbolic indexes into
+      // account.
+      if (!ER->getIndex().isConstant())
+        return UnknownVal();
     }
 
     return UndefinedVal();
@@ -1332,21 +1287,18 @@ SVal RegionStoreManager::RetrieveVar(Store store, const VarRegion *R) {
 }
 
 SVal RegionStoreManager::RetrieveLazySymbol(const TypedRegion *R) {
-
-  QualType valTy = R->getValueType(getContext());
-
   // All other values are symbolic.
   return ValMgr.getRegionValueSymbolVal(R);
 }
 
 SVal RegionStoreManager::RetrieveStruct(Store store, const TypedRegion* R) {
-  QualType T = R->getValueType(getContext());
+  QualType T = R->getValueType();
   assert(T->isStructureOrClassType());
   return ValMgr.makeLazyCompoundVal(store, R);
 }
 
 SVal RegionStoreManager::RetrieveArray(Store store, const TypedRegion * R) {
-  assert(isa<ConstantArrayType>(R->getValueType(getContext())));
+  assert(isa<ConstantArrayType>(R->getValueType()));
   return ValMgr.makeLazyCompoundVal(store, R);
 }
 
@@ -1371,38 +1323,26 @@ Store RegionStoreManager::Bind(Store store, Loc L, SVal V) {
 
   // Check if the region is a struct region.
   if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
-    if (TR->getValueType(getContext())->isStructureOrClassType())
+    if (TR->getValueType()->isStructureOrClassType())
       return BindStruct(store, TR, V);
 
-  // Special case: the current region represents a cast and it and the super
-  // region both have pointer types or intptr_t types.  If so, perform the
-  // bind to the super region.
-  // This is needed to support OSAtomicCompareAndSwap and friends or other
-  // loads that treat integers as pointers and vis versa.
   if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
     if (ER->getIndex().isZeroConstant()) {
       if (const TypedRegion *superR =
             dyn_cast<TypedRegion>(ER->getSuperRegion())) {
-        ASTContext &Ctx = getContext();
-        QualType superTy = superR->getValueType(Ctx);
-        QualType erTy = ER->getValueType(Ctx);
-
-        if (IsAnyPointerOrIntptr(superTy, Ctx) &&
-            IsAnyPointerOrIntptr(erTy, Ctx)) {
-          V = ValMgr.getSValuator().EvalCast(V, superTy, erTy);
-          return Bind(store, loc::MemRegionVal(superR), V);
-        }
+        QualType superTy = superR->getValueType();
         // For now, just invalidate the fields of the struct/union/class.
+        // This is for test rdar_test_7185607 in misc-ps-region-store.m.
         // FIXME: Precisely handle the fields of the record.
-        if (superTy->isRecordType())
-          return InvalidateRegion(store, superR, NULL, 0, NULL);
+        if (superTy->isStructureOrClassType())
+          return KillStruct(store, superR, UnknownVal());
       }
     }
   }
   else if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
     // Binding directly to a symbolic region should be treated as binding
     // to element 0.
-    QualType T = SR->getSymbol()->getType(getContext());
+    QualType T = SR->getSymbol()->getType(Ctx);
 
     // FIXME: Is this the right way to handle symbols that are references?
     if (const PointerType *PT = T->getAs<PointerType>())
@@ -1454,7 +1394,7 @@ Store RegionStoreManager::setImplicitDefaultValue(Store store,
   else if (T->isStructureOrClassType() || T->isArrayType()) {
     // Set the default value to a zero constant when it is a structure
     // or array.  The type doesn't really matter.
-    V = ValMgr.makeZeroVal(ValMgr.getContext().IntTy);
+    V = ValMgr.makeZeroVal(Ctx.IntTy);
   }
   else {
     return store;
@@ -1466,44 +1406,21 @@ Store RegionStoreManager::setImplicitDefaultValue(Store store,
 Store RegionStoreManager::BindArray(Store store, const TypedRegion* R,
                                     SVal Init) {
 
-  ASTContext &Ctx = getContext();
-  const ArrayType *AT =
-    cast<ArrayType>(Ctx.getCanonicalType(R->getValueType(Ctx)));
+  const ArrayType *AT =cast<ArrayType>(Ctx.getCanonicalType(R->getValueType()));
   QualType ElementTy = AT->getElementType();
   Optional<uint64_t> Size;
 
   if (const ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(AT))
     Size = CAT->getSize().getZExtValue();
 
-  // Check if the init expr is a StringLiteral.
-  if (isa<loc::MemRegionVal>(Init)) {
-    const MemRegion* InitR = cast<loc::MemRegionVal>(Init).getRegion();
-    const StringLiteral* S = cast<StringRegion>(InitR)->getStringLiteral();
-    const char* str = S->getStrData();
-    unsigned len = S->getByteLength();
-    unsigned j = 0;
-
-    // Copy bytes from the string literal into the target array. Trailing bytes
-    // in the array that are not covered by the string literal are initialized
-    // to zero.
+  // Check if the init expr is a string literal.
+  if (loc::MemRegionVal *MRV = dyn_cast<loc::MemRegionVal>(&Init)) {
+    const StringRegion *S = cast<StringRegion>(MRV->getRegion());
 
-    // We assume that string constants are bound to
-    // constant arrays.
-    uint64_t size = Size.getValue();
-
-    for (uint64_t i = 0; i < size; ++i, ++j) {
-      if (j >= len)
-        break;
-
-      SVal Idx = ValMgr.makeArrayIndex(i);
-      const ElementRegion* ER = MRMgr.getElementRegion(ElementTy, Idx, R,
-                                                       getContext());
-
-      SVal V = ValMgr.makeIntVal(str[j], sizeof(char)*8, true);
-      store = Bind(store, loc::MemRegionVal(ER), V);
-    }
-
-    return store;
+    // Treat the string as a lazy compound value.
+    nonloc::LazyCompoundVal LCV =
+      cast<nonloc::LazyCompoundVal>(ValMgr.makeLazyCompoundVal(store, S));
+    return CopyLazyBindings(LCV, store, R);
   }
 
   // Handle lazy compound values.
@@ -1525,10 +1442,12 @@ Store RegionStoreManager::BindArray(Store store, const TypedRegion* R,
       break;
 
     SVal Idx = ValMgr.makeArrayIndex(i);
-    const ElementRegion *ER = MRMgr.getElementRegion(ElementTy, Idx, R, getContext());
+    const ElementRegion *ER = MRMgr.getElementRegion(ElementTy, Idx, R, Ctx);
 
     if (ElementTy->isStructureOrClassType())
       store = BindStruct(store, ER, *VI);
+    else if (ElementTy->isArrayType())
+      store = BindArray(store, ER, *VI);
     else
       store = Bind(store, ValMgr.makeLoc(ER), *VI);
   }
@@ -1547,7 +1466,7 @@ Store RegionStoreManager::BindStruct(Store store, const TypedRegion* R,
   if (!Features.supportsFields())
     return store;
 
-  QualType T = R->getValueType(getContext());
+  QualType T = R->getValueType();
   assert(T->isStructureOrClassType());
 
   const RecordType* RT = T->getAs<RecordType>();
@@ -1560,10 +1479,13 @@ Store RegionStoreManager::BindStruct(Store store, const TypedRegion* R,
   if (const nonloc::LazyCompoundVal *LCV=dyn_cast<nonloc::LazyCompoundVal>(&V))
     return CopyLazyBindings(*LCV, store, R);
 
-  // We may get non-CompoundVal accidentally due to imprecise cast logic.
-  // Ignore them and kill the field values.
-  if (V.isUnknown() || !isa<nonloc::CompoundVal>(V))
-    return KillStruct(store, R);
+  // We may get non-CompoundVal accidentally due to imprecise cast logic or
+  // that we are binding symbolic struct value. Kill the field values, and if
+  // the value is symbolic go and bind it as a "default" binding.
+  if (V.isUnknown() || !isa<nonloc::CompoundVal>(V)) {
+    SVal SV = isa<nonloc::SymbolVal>(V) ? V : UnknownVal();
+    return KillStruct(store, R, SV);
+  }
 
   nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(V);
   nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
@@ -1596,14 +1518,15 @@ Store RegionStoreManager::BindStruct(Store store, const TypedRegion* R,
   return store;
 }
 
-Store RegionStoreManager::KillStruct(Store store, const TypedRegion* R) {
+Store RegionStoreManager::KillStruct(Store store, const TypedRegion* R,
+                                     SVal DefaultVal) {
   RegionBindings B = GetRegionBindings(store);
   llvm::OwningPtr<RegionStoreSubRegionMap>
     SubRegions(getRegionStoreSubRegionMap(store));
   RemoveSubRegionBindings(B, R, *SubRegions);
 
   // Set the default value of the struct region to "unknown".
-  return Add(B, R, BindingKey::Default, UnknownVal()).getRoot();
+  return Add(B, R, BindingKey::Default, DefaultVal).getRoot();
 }
 
 Store RegionStoreManager::CopyLazyBindings(nonloc::LazyCompoundVal V,
@@ -1627,21 +1550,10 @@ Store RegionStoreManager::CopyLazyBindings(nonloc::LazyCompoundVal V,
 // "Raw" retrievals and bindings.
 //===----------------------------------------------------------------------===//
 
-BindingKey BindingKey::Make(const MemRegion *R, Kind k) {
-  if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
-    const RegionRawOffset &O = ER->getAsRawOffset();
-
-    if (O.getRegion())
-      return BindingKey(O.getRegion(), O.getByteOffset(), k);
-
-    // FIXME: There are some ElementRegions for which we cannot compute
-    // raw offsets yet, including regions with symbolic offsets.
-  }
-
-  return BindingKey(R, 0, k);
-}
 
 RegionBindings RegionStoreManager::Add(RegionBindings B, BindingKey K, SVal V) {
+  if (!K.isValid())
+    return B;
   return RBFactory.Add(B, K, V);
 }
 
@@ -1651,6 +1563,8 @@ RegionBindings RegionStoreManager::Add(RegionBindings B, const MemRegion *R,
 }
 
 const SVal *RegionStoreManager::Lookup(RegionBindings B, BindingKey K) {
+  if (!K.isValid())
+    return NULL;
   return B.lookup(K);
 }
 
@@ -1661,6 +1575,8 @@ const SVal *RegionStoreManager::Lookup(RegionBindings B,
 }
 
 RegionBindings RegionStoreManager::Remove(RegionBindings B, BindingKey K) {
+  if (!K.isValid())
+    return B;
   return RBFactory.Remove(B, K);
 }
 
@@ -1669,11 +1585,6 @@ RegionBindings RegionStoreManager::Remove(RegionBindings B, const MemRegion *R,
   return Remove(B, BindingKey::Make(R, k));
 }
 
-Store RegionStoreManager::Remove(Store store, BindingKey K) {
-  RegionBindings B = GetRegionBindings(store);
-  return Remove(B, K).getRoot();
-}
-
 //===----------------------------------------------------------------------===//
 // State pruning.
 //===----------------------------------------------------------------------===//
@@ -1818,12 +1729,12 @@ bool RemoveDeadBindingsWorker::UpdatePostponed() {
   return changed;
 }
 
-const GRState *RegionStoreManager::RemoveDeadBindings(GRState &state,
+Store RegionStoreManager::RemoveDeadBindings(Store store,
                                              const StackFrameContext *LCtx,
                                              SymbolReaper& SymReaper,
                            llvm::SmallVectorImpl<const MemRegion*>& RegionRoots)
 {
-  RegionBindings B = GetRegionBindings(state.getStore());
+  RegionBindings B = GetRegionBindings(store);
   RemoveDeadBindingsWorker W(*this, StateMgr, B, SymReaper, LCtx);
   W.GenerateClusters();
 
@@ -1856,14 +1767,13 @@ const GRState *RegionStoreManager::RemoveDeadBindings(GRState &state,
     for (; SI != SE; ++SI)
       SymReaper.maybeDead(*SI);
   }
-  state.setStore(B.getRoot());
-  const GRState *s = StateMgr.getPersistentState(state);
-  return s;
+
+  return B.getRoot();
 }
 
 
-GRState const *RegionStoreManager::EnterStackFrame(GRState const *state,
-                                               StackFrameContext const *frame) {
+Store RegionStoreManager::EnterStackFrame(const GRState *state,
+                                          const StackFrameContext *frame) {
   FunctionDecl const *FD = cast<FunctionDecl>(frame->getDecl());
   FunctionDecl::param_const_iterator PI = FD->param_begin();
   Store store = state->getStore();
@@ -1887,9 +1797,9 @@ GRState const *RegionStoreManager::EnterStackFrame(GRState const *state,
       store = Bind(store, ValMgr.makeLoc(MRMgr.getVarRegion(*PI,frame)),ArgVal);
     }
   } else
-    assert(0 && "Unhandled call expression.");
+    llvm_unreachable("Unhandled call expression.");
 
-  return state->makeWithStore(store);
+  return store;
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/lib/Checker/ReturnPointerRangeChecker.cpp b/lib/Checker/ReturnPointerRangeChecker.cpp
index 14edf56..a9eb5ce 100644
--- a/lib/Checker/ReturnPointerRangeChecker.cpp
+++ b/lib/Checker/ReturnPointerRangeChecker.cpp
@@ -66,7 +66,7 @@ void ReturnPointerRangeChecker::PreVisitReturnStmt(CheckerContext &C,
 
   DefinedOrUnknownSVal NumElements
     = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(),
-                                           ER->getValueType(C.getASTContext()));
+                                           ER->getValueType());
 
   const GRState *StInBound = state->AssumeInBound(Idx, NumElements, true);
   const GRState *StOutBound = state->AssumeInBound(Idx, NumElements, false);
diff --git a/lib/Checker/ReturnUndefChecker.cpp b/lib/Checker/ReturnUndefChecker.cpp
index 52a0b30..73d1890 100644
--- a/lib/Checker/ReturnUndefChecker.cpp
+++ b/lib/Checker/ReturnUndefChecker.cpp
@@ -61,6 +61,7 @@ void ReturnUndefChecker::PreVisitReturnStmt(CheckerContext &C,
   EnhancedBugReport *report = 
     new EnhancedBugReport(*BT, BT->getDescription(), N);
 
+  report->addRange(RetE->getSourceRange());
   report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, RetE);
 
   C.EmitReport(report);
diff --git a/lib/Checker/SVals.cpp b/lib/Checker/SVals.cpp
index 7a99e86..97ba74e 100644
--- a/lib/Checker/SVals.cpp
+++ b/lib/Checker/SVals.cpp
@@ -62,6 +62,9 @@ const FunctionDecl *SVal::getAsFunctionDecl() const {
 ///  wraps a symbol, return that SymbolRef.  Otherwise return 0.
 // FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
 SymbolRef SVal::getAsLocSymbol() const {
+  if (const nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(this))
+    return X->getLoc().getAsLocSymbol();
+
   if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(this)) {
     const MemRegion *R = X->StripCasts();
     if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(R))
@@ -247,8 +250,8 @@ SVal loc::ConcreteInt::EvalBinOp(BasicValueFactory& BasicVals,
                                  BinaryOperator::Opcode Op,
                                  const loc::ConcreteInt& R) const {
 
-  assert (Op == BinaryOperator::Add || Op == BinaryOperator::Sub ||
-          (Op >= BinaryOperator::LT && Op <= BinaryOperator::NE));
+  assert (Op == BO_Add || Op == BO_Sub ||
+          (Op >= BO_LT && Op <= BO_NE));
 
   const llvm::APSInt* X = BasicVals.EvaluateAPSInt(Op, getValue(), R.getValue());
 
diff --git a/lib/Checker/SValuator.cpp b/lib/Checker/SValuator.cpp
index a7e15fc..273e574 100644
--- a/lib/Checker/SValuator.cpp
+++ b/lib/Checker/SValuator.cpp
@@ -37,7 +37,7 @@ SVal SValuator::EvalBinOp(const GRState *ST, BinaryOperator::Opcode Op,
   if (isa<Loc>(R)) {
     // Support pointer arithmetic where the addend is on the left
     // and the pointer on the right.
-    assert(Op == BinaryOperator::Add);
+    assert(Op == BO_Add);
 
     // Commute the operands.
     return EvalBinOpLN(ST, Op, cast<Loc>(R), cast<NonLoc>(L), T);
@@ -49,7 +49,7 @@ SVal SValuator::EvalBinOp(const GRState *ST, BinaryOperator::Opcode Op,
 DefinedOrUnknownSVal SValuator::EvalEQ(const GRState *ST,
                                        DefinedOrUnknownSVal L,
                                        DefinedOrUnknownSVal R) {
-  return cast<DefinedOrUnknownSVal>(EvalBinOp(ST, BinaryOperator::EQ, L, R,
+  return cast<DefinedOrUnknownSVal>(EvalBinOp(ST, BO_EQ, L, R,
                                               ValMgr.getContext().IntTy));
 }
 
diff --git a/lib/Checker/SimpleConstraintManager.cpp b/lib/Checker/SimpleConstraintManager.cpp
index 321381b..04496e1 100644
--- a/lib/Checker/SimpleConstraintManager.cpp
+++ b/lib/Checker/SimpleConstraintManager.cpp
@@ -31,17 +31,17 @@ bool SimpleConstraintManager::canReasonAbout(SVal X) const {
     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:
+        case BO_And:
+        case BO_Or:
+        case BO_Xor:
           return false;
         // We don't reason yet about these arithmetic constraints on
         // symbolic values.
-        case BinaryOperator::Mul:
-        case BinaryOperator::Div:
-        case BinaryOperator::Rem:
-        case BinaryOperator::Shl:
-        case BinaryOperator::Shr:
+        case BO_Mul:
+        case BO_Div:
+        case BO_Rem:
+        case BO_Shl:
+        case BO_Shr:
           return false;
         // All other cases.
         default:
@@ -125,12 +125,12 @@ static BinaryOperator::Opcode NegateComparison(BinaryOperator::Opcode op) {
   switch (op) {
   default:
     assert(false && "Invalid opcode.");
-  case BinaryOperator::LT: return BinaryOperator::GE;
-  case BinaryOperator::GT: return BinaryOperator::LE;
-  case BinaryOperator::LE: return BinaryOperator::GT;
-  case BinaryOperator::GE: return BinaryOperator::LT;
-  case BinaryOperator::EQ: return BinaryOperator::NE;
-  case BinaryOperator::NE: return BinaryOperator::EQ;
+  case BO_LT: return BO_GE;
+  case BO_GT: return BO_LE;
+  case BO_LE: return BO_GT;
+  case BO_GE: return BO_LT;
+  case BO_EQ: return BO_NE;
+  case BO_NE: return BO_EQ;
   }
 }
 
@@ -178,7 +178,7 @@ const GRState *SimpleConstraintManager::AssumeAux(const GRState *state,
     if (!BinaryOperator::isComparisonOp(op)) {
       QualType T = SymMgr.getType(SE);
       const llvm::APSInt &zero = BasicVals.getValue(0, T);
-      op = (Assumption ? BinaryOperator::NE : BinaryOperator::EQ);
+      op = (Assumption ? BO_NE : BO_EQ);
       return AssumeSymRel(state, SE, op, zero);
     }
 
@@ -238,10 +238,10 @@ const GRState *SimpleConstraintManager::AssumeSymRel(const GRState *state,
 
     // Get the constant out of the expression "($sym+constant1)".
     switch (SE->getOpcode()) {
-    case BinaryOperator::Add:
+    case BO_Add:
       Adjustment = SE->getRHS();
       break;
-    case BinaryOperator::Sub:
+    case BO_Sub:
       Adjustment = -SE->getRHS();
       break;
     default:
@@ -276,48 +276,24 @@ const GRState *SimpleConstraintManager::AssumeSymRel(const GRState *state,
     // No logic yet for other operators.  Assume the constraint is feasible.
     return state;
 
-  case BinaryOperator::EQ:
+  case BO_EQ:
     return AssumeSymEQ(state, Sym, ConvertedInt, Adjustment);
 
-  case BinaryOperator::NE:
+  case BO_NE:
     return AssumeSymNE(state, Sym, ConvertedInt, Adjustment);
 
-  case BinaryOperator::GT:
+  case BO_GT:
     return AssumeSymGT(state, Sym, ConvertedInt, Adjustment);
 
-  case BinaryOperator::GE:
+  case BO_GE:
     return AssumeSymGE(state, Sym, ConvertedInt, Adjustment);
 
-  case BinaryOperator::LT:
+  case BO_LT:
     return AssumeSymLT(state, Sym, ConvertedInt, Adjustment);
 
-  case BinaryOperator::LE:
+  case BO_LE:
     return AssumeSymLE(state, Sym, ConvertedInt, Adjustment);
   } // end switch
 }
 
-const GRState *SimpleConstraintManager::AssumeInBound(const GRState *state,
-                                                      DefinedSVal Idx,
-                                                      DefinedSVal UpperBound,
-                                                      bool Assumption) {
-
-  // Only support ConcreteInt for now.
-  if (!(isa<nonloc::ConcreteInt>(Idx) && isa<nonloc::ConcreteInt>(UpperBound)))
-    return state;
-
-  const llvm::APSInt& Zero = state->getBasicVals().getZeroWithPtrWidth(false);
-  llvm::APSInt IdxV = cast<nonloc::ConcreteInt>(Idx).getValue();
-  // IdxV might be too narrow.
-  if (IdxV.getBitWidth() < Zero.getBitWidth())
-    IdxV.extend(Zero.getBitWidth());
-  // UBV might be too narrow, too.
-  llvm::APSInt UBV = cast<nonloc::ConcreteInt>(UpperBound).getValue();
-  if (UBV.getBitWidth() < Zero.getBitWidth())
-    UBV.extend(Zero.getBitWidth());
-
-  bool InBound = (Zero <= IdxV) && (IdxV < UBV);
-  bool isFeasible = Assumption ? InBound : !InBound;
-  return isFeasible ? state : NULL;
-}
-
 }  // end of namespace clang
diff --git a/lib/Checker/SimpleConstraintManager.h b/lib/Checker/SimpleConstraintManager.h
index 45057e6..96811b3 100644
--- a/lib/Checker/SimpleConstraintManager.h
+++ b/lib/Checker/SimpleConstraintManager.h
@@ -43,10 +43,6 @@ public:
                               BinaryOperator::Opcode op,
                               const llvm::APSInt& Int);
 
-  const GRState *AssumeInBound(const GRState *state, DefinedSVal Idx,
-                               DefinedSVal UpperBound,
-                               bool Assumption);
-
 protected:
 
   //===------------------------------------------------------------------===//
diff --git a/lib/Checker/SimpleSValuator.cpp b/lib/Checker/SimpleSValuator.cpp
index 3bc4ee7..782cd4f 100644
--- a/lib/Checker/SimpleSValuator.cpp
+++ b/lib/Checker/SimpleSValuator.cpp
@@ -168,12 +168,12 @@ static BinaryOperator::Opcode NegateComparison(BinaryOperator::Opcode op) {
   switch (op) {
   default:
     assert(false && "Invalid opcode.");
-  case BinaryOperator::LT: return BinaryOperator::GE;
-  case BinaryOperator::GT: return BinaryOperator::LE;
-  case BinaryOperator::LE: return BinaryOperator::GT;
-  case BinaryOperator::GE: return BinaryOperator::LT;
-  case BinaryOperator::EQ: return BinaryOperator::NE;
-  case BinaryOperator::NE: return BinaryOperator::EQ;
+  case BO_LT: return BO_GE;
+  case BO_GT: return BO_LE;
+  case BO_LE: return BO_GT;
+  case BO_GE: return BO_LT;
+  case BO_EQ: return BO_NE;
+  case BO_NE: return BO_EQ;
   }
 }
 
@@ -181,12 +181,12 @@ static BinaryOperator::Opcode ReverseComparison(BinaryOperator::Opcode op) {
   switch (op) {
   default:
     assert(false && "Invalid opcode.");
-  case BinaryOperator::LT: return BinaryOperator::GT;
-  case BinaryOperator::GT: return BinaryOperator::LT;
-  case BinaryOperator::LE: return BinaryOperator::GE;
-  case BinaryOperator::GE: return BinaryOperator::LE;
-  case BinaryOperator::EQ:
-  case BinaryOperator::NE:
+  case BO_LT: return BO_GT;
+  case BO_GT: return BO_LT;
+  case BO_LE: return BO_GE;
+  case BO_GE: return BO_LE;
+  case BO_EQ:
+  case BO_NE:
     return op;
   }
 }
@@ -202,14 +202,14 @@ SVal SimpleSValuator::MakeSymIntVal(const SymExpr *LHS,
   default:
     // We can't reduce this case; just treat it normally.
     break;
-  case BinaryOperator::Mul:
+  case BO_Mul:
     // a*0 and a*1
     if (RHS == 0)
       return ValMgr.makeIntVal(0, resultTy);
     else if (RHS == 1)
       isIdempotent = true;
     break;
-  case BinaryOperator::Div:
+  case BO_Div:
     // a/0 and a/1
     if (RHS == 0)
       // This is also handled elsewhere.
@@ -217,7 +217,7 @@ SVal SimpleSValuator::MakeSymIntVal(const SymExpr *LHS,
     else if (RHS == 1)
       isIdempotent = true;
     break;
-  case BinaryOperator::Rem:
+  case BO_Rem:
     // a%0 and a%1
     if (RHS == 0)
       // This is also handled elsewhere.
@@ -225,23 +225,23 @@ SVal SimpleSValuator::MakeSymIntVal(const SymExpr *LHS,
     else if (RHS == 1)
       return ValMgr.makeIntVal(0, resultTy);
     break;
-  case BinaryOperator::Add:
-  case BinaryOperator::Sub:
-  case BinaryOperator::Shl:
-  case BinaryOperator::Shr:
-  case BinaryOperator::Xor:
+  case BO_Add:
+  case BO_Sub:
+  case BO_Shl:
+  case BO_Shr:
+  case BO_Xor:
     // a+0, a-0, a<<0, a>>0, a^0
     if (RHS == 0)
       isIdempotent = true;
     break;
-  case BinaryOperator::And:
+  case BO_And:
     // a&0 and a&(~0)
     if (RHS == 0)
       return ValMgr.makeIntVal(0, resultTy);
     else if (RHS.isAllOnesValue())
       isIdempotent = true;
     break;
-  case BinaryOperator::Or:
+  case BO_Or:
     // a|0 and a|(~0)
     if (RHS == 0)
       isIdempotent = true;
@@ -275,19 +275,19 @@ SVal SimpleSValuator::EvalBinOpNN(const GRState *state,
     switch (op) {
       default:
         break;
-      case BinaryOperator::EQ:
-      case BinaryOperator::LE:
-      case BinaryOperator::GE:
+      case BO_EQ:
+      case BO_LE:
+      case BO_GE:
         return ValMgr.makeTruthVal(true, resultTy);
-      case BinaryOperator::LT:
-      case BinaryOperator::GT:
-      case BinaryOperator::NE:
+      case BO_LT:
+      case BO_GT:
+      case BO_NE:
         return ValMgr.makeTruthVal(false, resultTy);
-      case BinaryOperator::Xor:
-      case BinaryOperator::Sub:
+      case BO_Xor:
+      case BO_Sub:
         return ValMgr.makeIntVal(0, resultTy);
-      case BinaryOperator::Or:
-      case BinaryOperator::And:
+      case BO_Or:
+      case BO_And:
         return EvalCastNL(lhs, resultTy);
     }
 
@@ -312,9 +312,9 @@ SVal SimpleSValuator::EvalBinOpNN(const GRState *state,
         }
         default:
           switch (op) {
-            case BinaryOperator::EQ:
+            case BO_EQ:
               return ValMgr.makeTruthVal(false, resultTy);
-            case BinaryOperator::NE:
+            case BO_NE:
               return ValMgr.makeTruthVal(true, resultTy);
             default:
               // This case also handles pointer arithmetic.
@@ -333,7 +333,7 @@ SVal SimpleSValuator::EvalBinOpNN(const GRState *state,
         return UnknownVal();
 
       // Is this a logical not? (!x is represented as x == 0.)
-      if (op == BinaryOperator::EQ && rhs.isZeroConstant()) {
+      if (op == BO_EQ && rhs.isZeroConstant()) {
         // We know how to negate certain expressions. Simplify them here.
 
         BinaryOperator::Opcode opc = symIntExpr->getOpcode();
@@ -342,34 +342,34 @@ SVal SimpleSValuator::EvalBinOpNN(const GRState *state,
           // We don't know how to negate this operation.
           // Just handle it as if it were a normal comparison to 0.
           break;
-        case BinaryOperator::LAnd:
-        case BinaryOperator::LOr:
+        case BO_LAnd:
+        case BO_LOr:
           assert(false && "Logical operators handled by branching logic.");
           return UnknownVal();
-        case BinaryOperator::Assign:
-        case BinaryOperator::MulAssign:
-        case BinaryOperator::DivAssign:
-        case BinaryOperator::RemAssign:
-        case BinaryOperator::AddAssign:
-        case BinaryOperator::SubAssign:
-        case BinaryOperator::ShlAssign:
-        case BinaryOperator::ShrAssign:
-        case BinaryOperator::AndAssign:
-        case BinaryOperator::XorAssign:
-        case BinaryOperator::OrAssign:
-        case BinaryOperator::Comma:
+        case BO_Assign:
+        case BO_MulAssign:
+        case BO_DivAssign:
+        case BO_RemAssign:
+        case BO_AddAssign:
+        case BO_SubAssign:
+        case BO_ShlAssign:
+        case BO_ShrAssign:
+        case BO_AndAssign:
+        case BO_XorAssign:
+        case BO_OrAssign:
+        case BO_Comma:
           assert(false && "'=' and ',' operators handled by GRExprEngine.");
           return UnknownVal();
-        case BinaryOperator::PtrMemD:
-        case BinaryOperator::PtrMemI:
+        case BO_PtrMemD:
+        case BO_PtrMemI:
           assert(false && "Pointer arithmetic not handled here.");
           return UnknownVal();
-        case BinaryOperator::LT:
-        case BinaryOperator::GT:
-        case BinaryOperator::LE:
-        case BinaryOperator::GE:
-        case BinaryOperator::EQ:
-        case BinaryOperator::NE:
+        case BO_LT:
+        case BO_GT:
+        case BO_LE:
+        case BO_GE:
+        case BO_EQ:
+        case BO_NE:
           // Negate the comparison and make a value.
           opc = NegateComparison(opc);
           assert(symIntExpr->getType(ValMgr.getContext()) == resultTy);
@@ -402,9 +402,9 @@ SVal SimpleSValuator::EvalBinOpNN(const GRState *state,
 
           const llvm::APSInt *newRHS;
           if (lop == op)
-            newRHS = BVF.EvaluateAPSInt(BinaryOperator::Add, first, second);
+            newRHS = BVF.EvaluateAPSInt(BO_Add, first, second);
           else
-            newRHS = BVF.EvaluateAPSInt(BinaryOperator::Sub, first, second);
+            newRHS = BVF.EvaluateAPSInt(BO_Sub, first, second);
           return MakeSymIntVal(symIntExpr->getLHS(), lop, *newRHS, resultTy);
         }
       }
@@ -429,26 +429,26 @@ SVal SimpleSValuator::EvalBinOpNN(const GRState *state,
         lhs = tmp;
 
         switch (op) {
-          case BinaryOperator::LT:
-          case BinaryOperator::GT:
-          case BinaryOperator::LE:
-          case BinaryOperator::GE:
+          case BO_LT:
+          case BO_GT:
+          case BO_LE:
+          case BO_GE:
             op = ReverseComparison(op);
             continue;
-          case BinaryOperator::EQ:
-          case BinaryOperator::NE:
-          case BinaryOperator::Add:
-          case BinaryOperator::Mul:
-          case BinaryOperator::And:
-          case BinaryOperator::Xor:
-          case BinaryOperator::Or:
+          case BO_EQ:
+          case BO_NE:
+          case BO_Add:
+          case BO_Mul:
+          case BO_And:
+          case BO_Xor:
+          case BO_Or:
             continue;
-          case BinaryOperator::Shr:
+          case BO_Shr:
             if (lhsValue.isAllOnesValue() && lhsValue.isSigned())
               // At this point lhs and rhs have been swapped.
               return rhs;
             // FALL-THROUGH
-          case BinaryOperator::Shl:
+          case BO_Shl:
             if (lhsValue == 0)
               // At this point lhs and rhs have been swapped.
               return rhs;
@@ -461,10 +461,12 @@ SVal SimpleSValuator::EvalBinOpNN(const GRState *state,
     case nonloc::SymbolValKind: {
       nonloc::SymbolVal *slhs = cast<nonloc::SymbolVal>(&lhs);
       SymbolRef Sym = slhs->getSymbol();
-      
+
+      ASTContext& Ctx = ValMgr.getContext();
+
       // Does the symbol simplify to a constant?  If so, "fold" the constant
       // by setting 'lhs' to a ConcreteInt and try again.
-      if (Sym->getType(ValMgr.getContext())->isIntegerType())
+      if (Sym->getType(Ctx)->isIntegerType())
         if (const llvm::APSInt *Constant = state->getSymVal(Sym)) {
           // The symbol evaluates to a constant. If necessary, promote the
           // folded constant (LHS) to the result type.
@@ -474,7 +476,7 @@ SVal SimpleSValuator::EvalBinOpNN(const GRState *state,
           
           // Also promote the RHS (if necessary).
 
-          // For shifts, it necessary promote the RHS to the result type.
+          // For shifts, it is not necessary to promote the RHS.
           if (BinaryOperator::isShiftOp(op))
             continue;
           
@@ -486,7 +488,20 @@ SVal SimpleSValuator::EvalBinOpNN(const GRState *state,
           
           continue;
         }
-      
+
+      // Is the RHS a symbol we can simplify?
+      if (const nonloc::SymbolVal *srhs = dyn_cast<nonloc::SymbolVal>(&rhs)) {
+        SymbolRef RSym = srhs->getSymbol();
+        if (RSym->getType(Ctx)->isIntegerType()) {
+          if (const llvm::APSInt *Constant = state->getSymVal(RSym)) {
+            // The symbol evaluates to a constant.
+            BasicValueFactory &BVF = ValMgr.getBasicValueFactory();
+            const llvm::APSInt &rhs_I = BVF.Convert(resultTy, *Constant);
+            rhs = nonloc::ConcreteInt(rhs_I);
+          }
+        }
+      }
+
       if (isa<nonloc::ConcreteInt>(rhs)) {
         return MakeSymIntVal(slhs->getSymbol(), op,
                              cast<nonloc::ConcreteInt>(rhs).getValue(),
@@ -510,7 +525,7 @@ SVal SimpleSValuator::EvalBinOpLL(const GRState *state,
   // calling this function with another operation (PR7527). We don't attempt to
   // model this for now, but it could be useful, particularly when the
   // "location" is actually an integer value that's been passed through a void*.
-  if (!(BinaryOperator::isComparisonOp(op) || op == BinaryOperator::Sub))
+  if (!(BinaryOperator::isComparisonOp(op) || op == BO_Sub))
     return UnknownVal();
 
   // Special cases for when both sides are identical.
@@ -519,15 +534,15 @@ SVal SimpleSValuator::EvalBinOpLL(const GRState *state,
     default:
       assert(false && "Unimplemented operation for two identical values");
       return UnknownVal();
-    case BinaryOperator::Sub:
+    case BO_Sub:
       return ValMgr.makeZeroVal(resultTy);
-    case BinaryOperator::EQ:
-    case BinaryOperator::LE:
-    case BinaryOperator::GE:
+    case BO_EQ:
+    case BO_LE:
+    case BO_GE:
       return ValMgr.makeTruthVal(true, resultTy);
-    case BinaryOperator::NE:
-    case BinaryOperator::LT:
-    case BinaryOperator::GT:
+    case BO_NE:
+    case BO_LT:
+    case BO_GT:
       return ValMgr.makeTruthVal(false, resultTy);
     }
   }
@@ -543,15 +558,15 @@ SVal SimpleSValuator::EvalBinOpLL(const GRState *state,
       switch (op) {
       default:
         break;
-      case BinaryOperator::Sub:
+      case BO_Sub:
         return EvalCastL(lhs, resultTy);
-      case BinaryOperator::EQ:
-      case BinaryOperator::LE:
-      case BinaryOperator::LT:
+      case BO_EQ:
+      case BO_LE:
+      case BO_LT:
         return ValMgr.makeTruthVal(false, resultTy);
-      case BinaryOperator::NE:
-      case BinaryOperator::GT:
-      case BinaryOperator::GE:
+      case BO_NE:
+      case BO_GT:
+      case BO_GE:
         return ValMgr.makeTruthVal(true, resultTy);
       }
     }
@@ -594,13 +609,13 @@ SVal SimpleSValuator::EvalBinOpLL(const GRState *state,
       switch (op) {
       default:
         break;
-      case BinaryOperator::EQ:
-      case BinaryOperator::GT:
-      case BinaryOperator::GE:
+      case BO_EQ:
+      case BO_GT:
+      case BO_GE:
         return ValMgr.makeTruthVal(false, resultTy);
-      case BinaryOperator::NE:
-      case BinaryOperator::LT:
-      case BinaryOperator::LE:
+      case BO_NE:
+      case BO_LT:
+      case BO_LE:
         return ValMgr.makeTruthVal(true, resultTy);
       }
     }
@@ -624,15 +639,15 @@ SVal SimpleSValuator::EvalBinOpLL(const GRState *state,
         switch (op) {
         default:
           break;
-        case BinaryOperator::Sub:
+        case BO_Sub:
           return EvalCastL(lhs, resultTy);
-        case BinaryOperator::EQ:
-        case BinaryOperator::LT:
-        case BinaryOperator::LE:
+        case BO_EQ:
+        case BO_LT:
+        case BO_LE:
           return ValMgr.makeTruthVal(false, resultTy);
-        case BinaryOperator::NE:
-        case BinaryOperator::GT:
-        case BinaryOperator::GE:
+        case BO_NE:
+        case BO_GT:
+        case BO_GE:
           return ValMgr.makeTruthVal(true, resultTy);
         }
       }
@@ -660,9 +675,9 @@ SVal SimpleSValuator::EvalBinOpLL(const GRState *state,
       switch (op) {
       default:
         return UnknownVal();
-      case BinaryOperator::EQ:
+      case BO_EQ:
         return ValMgr.makeTruthVal(false, resultTy);
-      case BinaryOperator::NE:
+      case BO_NE:
         return ValMgr.makeTruthVal(true, resultTy);
       }
     }
@@ -711,8 +726,8 @@ SVal SimpleSValuator::EvalBinOpLL(const GRState *state,
       }
 
       // If the element indexes aren't comparable, see if the raw offsets are.
-      RegionRawOffset LeftOffset = LeftER->getAsRawOffset();
-      RegionRawOffset RightOffset = RightER->getAsRawOffset();
+      RegionRawOffset LeftOffset = LeftER->getAsArrayOffset();
+      RegionRawOffset RightOffset = RightER->getAsArrayOffset();
 
       if (LeftOffset.getRegion() != NULL &&
           LeftOffset.getRegion() == RightOffset.getRegion()) {
@@ -722,17 +737,17 @@ SVal SimpleSValuator::EvalBinOpLL(const GRState *state,
         switch (op) {
         default:
           return UnknownVal();
-        case BinaryOperator::LT:
+        case BO_LT:
           return ValMgr.makeTruthVal(left < right, resultTy);
-        case BinaryOperator::GT:
+        case BO_GT:
           return ValMgr.makeTruthVal(left > right, resultTy);
-        case BinaryOperator::LE:
+        case BO_LE:
           return ValMgr.makeTruthVal(left <= right, resultTy);
-        case BinaryOperator::GE:
+        case BO_GE:
           return ValMgr.makeTruthVal(left >= right, resultTy);
-        case BinaryOperator::EQ:
+        case BO_EQ:
           return ValMgr.makeTruthVal(left == right, resultTy);
-        case BinaryOperator::NE:
+        case BO_NE:
           return ValMgr.makeTruthVal(left != right, resultTy);
         }
       }
@@ -770,16 +785,16 @@ SVal SimpleSValuator::EvalBinOpLL(const GRState *state,
 
       // We know for sure that the two fields are not the same, since that
       // would have given us the same SVal.
-      if (op == BinaryOperator::EQ)
+      if (op == BO_EQ)
         return ValMgr.makeTruthVal(false, resultTy);
-      if (op == BinaryOperator::NE)
+      if (op == BO_NE)
         return ValMgr.makeTruthVal(true, resultTy);
 
       // Iterate through the fields and see which one comes first.
       // [C99 6.7.2.1.13] "Within a structure object, the non-bit-field
       // members and the units in which bit-fields reside have addresses that
       // increase in the order in which they are declared."
-      bool leftFirst = (op == BinaryOperator::LT || op == BinaryOperator::LE);
+      bool leftFirst = (op == BO_LT || op == BO_LE);
       for (RecordDecl::field_iterator I = RD->field_begin(),
            E = RD->field_end(); I!=E; ++I) {
         if (*I == LeftFD)
@@ -818,8 +833,41 @@ SVal SimpleSValuator::EvalBinOpLN(const GRState *state,
       }
     }
   }
+  
+  // We are dealing with pointer arithmetic.
+
+  // Handle pointer arithmetic on constant values.
+  if (nonloc::ConcreteInt *rhsInt = dyn_cast<nonloc::ConcreteInt>(&rhs)) {
+    if (loc::ConcreteInt *lhsInt = dyn_cast<loc::ConcreteInt>(&lhs)) {
+      const llvm::APSInt &leftI = lhsInt->getValue();
+      assert(leftI.isUnsigned());
+      llvm::APSInt rightI(rhsInt->getValue(), /* isUnsigned */ true);
+
+      // Convert the bitwidth of rightI.  This should deal with overflow
+      // since we are dealing with concrete values.
+      rightI.extOrTrunc(leftI.getBitWidth());
+
+      // Offset the increment by the pointer size.
+      llvm::APSInt Multiplicand(rightI.getBitWidth(), /* isUnsigned */ true);
+      rightI *= Multiplicand;
+      
+      // Compute the adjusted pointer.
+      switch (op) {
+        case BO_Add:
+          rightI = leftI + rightI;
+          break;
+        case BO_Sub:
+          rightI = leftI - rightI;
+          break;
+        default:
+          llvm_unreachable("Invalid pointer arithmetic operation");
+      }
+      return loc::ConcreteInt(ValMgr.getBasicValueFactory().getValue(rightI));
+    }
+  }
+  
 
-  // Delegate pointer arithmetic to the StoreManager.
+  // Delegate remaining pointer arithmetic to the StoreManager.
   return state->getStateManager().getStoreManager().EvalBinOp(op, lhs,
                                                               rhs, resultTy);
 }
diff --git a/lib/Checker/StackAddrLeakChecker.cpp b/lib/Checker/StackAddrLeakChecker.cpp
index f4a9db6..c67a81d 100644
--- a/lib/Checker/StackAddrLeakChecker.cpp
+++ b/lib/Checker/StackAddrLeakChecker.cpp
@@ -108,7 +108,7 @@ void StackAddrLeakChecker::EmitStackError(CheckerContext &C, const MemRegion *R,
     report->addRange(range);
 
   C.EmitReport(report);
-}	
+}
 
 void StackAddrLeakChecker::PreVisitReturnStmt(CheckerContext &C,
                                               const ReturnStmt *RS) {
diff --git a/lib/Checker/Store.cpp b/lib/Checker/Store.cpp
index b128331..1cb5cd7 100644
--- a/lib/Checker/Store.cpp
+++ b/lib/Checker/Store.cpp
@@ -21,6 +21,11 @@ StoreManager::StoreManager(GRStateManager &stateMgr)
   : ValMgr(stateMgr.getValueManager()), StateMgr(stateMgr),
     MRMgr(ValMgr.getRegionManager()), Ctx(stateMgr.getContext()) {}
 
+Store StoreManager::EnterStackFrame(const GRState *state,
+                                    const StackFrameContext *frame) {
+  return state->getStore();
+}
+
 const MemRegion *StoreManager::MakeElementRegion(const MemRegion *Base,
                                               QualType EleTy, uint64_t index) {
   SVal idx = ValMgr.makeArrayIndex(index);
@@ -78,7 +83,7 @@ const MemRegion *StoreManager::CastRegion(const MemRegion *R, QualType CastToTy)
   // Handle casts from compatible types.
   if (R->isBoundable())
     if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {
-      QualType ObjTy = Ctx.getCanonicalType(TR->getValueType(Ctx));
+      QualType ObjTy = Ctx.getCanonicalType(TR->getValueType());
       if (CanonPointeeTy == ObjTy)
         return R;
     }
@@ -96,17 +101,10 @@ const MemRegion *StoreManager::CastRegion(const MemRegion *R, QualType CastToTy)
       assert(0 && "Invalid region cast");
       break;
     }
-    
+
     case MemRegion::FunctionTextRegionKind:
     case MemRegion::BlockTextRegionKind:
-    case MemRegion::BlockDataRegionKind: {
-      // CodeTextRegion should be cast to only a function or block pointer type,
-      // although they can in practice be casted to anything, e.g, void*, char*,
-      // etc.  
-      // Just return the region.
-      return R;
-    }
-
+    case MemRegion::BlockDataRegionKind:
     case MemRegion::StringRegionKind:
       // FIXME: Need to handle arbitrary downcasts.
     case MemRegion::SymbolicRegionKind:
@@ -139,7 +137,7 @@ const MemRegion *StoreManager::CastRegion(const MemRegion *R, QualType CastToTy)
       // FIXME: Handle symbolic raw offsets.
 
       const ElementRegion *elementR = cast<ElementRegion>(R);
-      const RegionRawOffset &rawOff = elementR->getAsRawOffset();
+      const RegionRawOffset &rawOff = elementR->getAsArrayOffset();
       const MemRegion *baseR = rawOff.getRegion();
 
       // If we cannot compute a raw offset, throw up our hands and return
@@ -154,7 +152,7 @@ const MemRegion *StoreManager::CastRegion(const MemRegion *R, QualType CastToTy)
         // check to see if type we are casting to is the same as the base
         // region.  If so, just return the base region.
         if (const TypedRegion *TR = dyn_cast<TypedRegion>(baseR)) {
-          QualType ObjTy = Ctx.getCanonicalType(TR->getValueType(Ctx));
+          QualType ObjTy = Ctx.getCanonicalType(TR->getValueType());
           QualType CanonPointeeTy = Ctx.getCanonicalType(PointeeTy);
           if (CanonPointeeTy == ObjTy)
             return baseR;
@@ -217,7 +215,7 @@ SVal StoreManager::CastRetrievedVal(SVal V, const TypedRegion *R,
 
   if (performTestOnly) {  
     // Automatically translate references to pointers.
-    QualType T = R->getValueType(Ctx);
+    QualType T = R->getValueType();
     if (const ReferenceType *RT = T->getAs<ReferenceType>())
       T = Ctx.getPointerType(RT->getPointeeType());
     
@@ -279,10 +277,6 @@ SVal StoreManager::getLValueElement(QualType elementType, SVal Offset,
   if (Base.isUnknownOrUndef() || isa<loc::ConcreteInt>(Base))
     return Base;
 
-  // Only handle integer offsets... for now.
-  if (!isa<nonloc::ConcreteInt>(Offset))
-    return UnknownVal();
-
   const MemRegion* BaseRegion = cast<loc::MemRegionVal>(Base).getRegion();
 
   // Pointer of any type can be cast and used as array base.
@@ -311,6 +305,19 @@ SVal StoreManager::getLValueElement(QualType elementType, SVal Offset,
     return UnknownVal();
 
   const llvm::APSInt& BaseIdxI = cast<nonloc::ConcreteInt>(BaseIdx).getValue();
+
+  // Only allow non-integer offsets if the base region has no offset itself.
+  // FIXME: This is a somewhat arbitrary restriction. We should be using
+  // SValuator here to add the two offsets without checking their types.
+  if (!isa<nonloc::ConcreteInt>(Offset)) {
+    if (isa<ElementRegion>(BaseRegion->StripCasts()))
+      return UnknownVal();
+
+    return loc::MemRegionVal(MRMgr.getElementRegion(elementType, Offset,
+                                                    ElemR->getSuperRegion(),
+                                                    Ctx));
+  }
+
   const llvm::APSInt& OffI = cast<nonloc::ConcreteInt>(Offset).getValue();
   assert(BaseIdxI.isSigned());
 
diff --git a/lib/Checker/StreamChecker.cpp b/lib/Checker/StreamChecker.cpp
index c527ca2..8553875 100644
--- a/lib/Checker/StreamChecker.cpp
+++ b/lib/Checker/StreamChecker.cpp
@@ -23,18 +23,49 @@ using namespace clang;
 
 namespace {
 
+struct StreamState {
+  enum Kind { Opened, Closed, OpenFailed, Escaped } K;
+  const Stmt *S;
+
+  StreamState(Kind k, const Stmt *s) : K(k), S(s) {}
+
+  bool isOpened() const { return K == Opened; }
+  bool isClosed() const { return K == Closed; }
+  //bool isOpenFailed() const { return K == OpenFailed; }
+  //bool isEscaped() const { return K == Escaped; }
+
+  bool operator==(const StreamState &X) const {
+    return K == X.K && S == X.S;
+  }
+
+  static StreamState getOpened(const Stmt *s) { return StreamState(Opened, s); }
+  static StreamState getClosed(const Stmt *s) { return StreamState(Closed, s); }
+  static StreamState getOpenFailed(const Stmt *s) { 
+    return StreamState(OpenFailed, s); 
+  }
+  static StreamState getEscaped(const Stmt *s) {
+    return StreamState(Escaped, s);
+  }
+
+  void Profile(llvm::FoldingSetNodeID &ID) const {
+    ID.AddInteger(K);
+    ID.AddPointer(S);
+  }
+};
+
 class StreamChecker : public CheckerVisitor<StreamChecker> {
-  IdentifierInfo *II_fopen, *II_fread, *II_fwrite, 
+  IdentifierInfo *II_fopen, *II_tmpfile, *II_fclose, *II_fread, *II_fwrite, 
                  *II_fseek, *II_ftell, *II_rewind, *II_fgetpos, *II_fsetpos,  
                  *II_clearerr, *II_feof, *II_ferror, *II_fileno;
-  BuiltinBug *BT_nullfp, *BT_illegalwhence;
+  BuiltinBug *BT_nullfp, *BT_illegalwhence, *BT_doubleclose, *BT_ResourceLeak;
 
 public:
   StreamChecker() 
-    : II_fopen(0), II_fread(0), II_fwrite(0), 
+    : II_fopen(0), II_tmpfile(0) ,II_fclose(0), II_fread(0), II_fwrite(0), 
       II_fseek(0), II_ftell(0), II_rewind(0), II_fgetpos(0), II_fsetpos(0), 
       II_clearerr(0), II_feof(0), II_ferror(0), II_fileno(0), 
-      BT_nullfp(0), BT_illegalwhence(0) {}
+      BT_nullfp(0), BT_illegalwhence(0), BT_doubleclose(0), 
+      BT_ResourceLeak(0) {}
 
   static void *getTag() {
     static int x;
@@ -42,9 +73,14 @@ public:
   }
 
   virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
+  void EvalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper);
+  void EvalEndPath(GREndPathNodeBuilder &B, void *tag, GRExprEngine &Eng);
+  void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S);
 
 private:
   void Fopen(CheckerContext &C, const CallExpr *CE);
+  void Tmpfile(CheckerContext &C, const CallExpr *CE);
+  void Fclose(CheckerContext &C, const CallExpr *CE);
   void Fread(CheckerContext &C, const CallExpr *CE);
   void Fwrite(CheckerContext &C, const CallExpr *CE);
   void Fseek(CheckerContext &C, const CallExpr *CE);
@@ -56,14 +92,25 @@ private:
   void Feof(CheckerContext &C, const CallExpr *CE);
   void Ferror(CheckerContext &C, const CallExpr *CE);
   void Fileno(CheckerContext &C, const CallExpr *CE);
+
+  void OpenFileAux(CheckerContext &C, const CallExpr *CE);
   
-  // Return true indicates the stream pointer is NULL.
   const GRState *CheckNullStream(SVal SV, const GRState *state, 
                                  CheckerContext &C);
+  const GRState *CheckDoubleClose(const CallExpr *CE, const GRState *state, 
+                                 CheckerContext &C);
 };
 
 } // end anonymous namespace
 
+namespace clang {
+  template <>
+  struct GRStateTrait<StreamState> 
+    : public GRStatePartialTrait<llvm::ImmutableMap<SymbolRef, StreamState> > {
+    static void *GDMIndex() { return StreamChecker::getTag(); }
+  };
+}
+
 void clang::RegisterStreamChecker(GRExprEngine &Eng) {
   Eng.registerCheck(new StreamChecker());
 }
@@ -79,6 +126,10 @@ bool StreamChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
   ASTContext &Ctx = C.getASTContext();
   if (!II_fopen)
     II_fopen = &Ctx.Idents.get("fopen");
+  if (!II_tmpfile)
+    II_tmpfile = &Ctx.Idents.get("tmpfile");
+  if (!II_fclose)
+    II_fclose = &Ctx.Idents.get("fclose");
   if (!II_fread)
     II_fread = &Ctx.Idents.get("fread");
   if (!II_fwrite)
@@ -106,6 +157,14 @@ bool StreamChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
     Fopen(C, CE);
     return true;
   }
+  if (FD->getIdentifier() == II_tmpfile) {
+    Tmpfile(C, CE);
+    return true;
+  }
+  if (FD->getIdentifier() == II_fclose) {
+    Fclose(C, CE);
+    return true;
+  }
   if (FD->getIdentifier() == II_fread) {
     Fread(C, CE);
     return true;
@@ -155,21 +214,43 @@ bool StreamChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
 }
 
 void StreamChecker::Fopen(CheckerContext &C, const CallExpr *CE) {
+  OpenFileAux(C, CE);
+}
+
+void StreamChecker::Tmpfile(CheckerContext &C, const CallExpr *CE) {
+  OpenFileAux(C, CE);
+}
+
+void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) {
   const GRState *state = C.getState();
   unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
   ValueManager &ValMgr = C.getValueManager();
   DefinedSVal RetVal = cast<DefinedSVal>(ValMgr.getConjuredSymbolVal(0, CE, 
                                                                      Count));
   state = state->BindExpr(CE, RetVal);
-
+  
   ConstraintManager &CM = C.getConstraintManager();
   // Bifurcate the state into two: one with a valid FILE* pointer, the other
   // with a NULL.
   const GRState *stateNotNull, *stateNull;
   llvm::tie(stateNotNull, stateNull) = CM.AssumeDual(state, RetVal);
+  
+  if (SymbolRef Sym = RetVal.getAsSymbol()) {
+    // if RetVal is not NULL, set the symbol's state to Opened.
+    stateNotNull =
+      stateNotNull->set<StreamState>(Sym,StreamState::getOpened(CE));
+    stateNull =
+      stateNull->set<StreamState>(Sym, StreamState::getOpenFailed(CE));
+
+    C.addTransition(stateNotNull);
+    C.addTransition(stateNull);
+  }
+}
 
-  C.addTransition(stateNotNull);
-  C.addTransition(stateNull);
+void StreamChecker::Fclose(CheckerContext &C, const CallExpr *CE) {
+  const GRState *state = CheckDoubleClose(CE, C.getState(), C);
+  if (state)
+    C.addTransition(state);
 }
 
 void StreamChecker::Fread(CheckerContext &C, const CallExpr *CE) {
@@ -285,3 +366,103 @@ const GRState *StreamChecker::CheckNullStream(SVal SV, const GRState *state,
   }
   return stateNotNull;
 }
+
+const GRState *StreamChecker::CheckDoubleClose(const CallExpr *CE,
+                                               const GRState *state,
+                                               CheckerContext &C) {
+  SymbolRef Sym = state->getSVal(CE->getArg(0)).getAsSymbol();
+  if (!Sym)
+    return state;
+  
+  const StreamState *SS = state->get<StreamState>(Sym);
+
+  // If the file stream is not tracked, return.
+  if (!SS)
+    return state;
+  
+  // Check: Double close a File Descriptor could cause undefined behaviour.
+  // Conforming to man-pages
+  if (SS->isClosed()) {
+    ExplodedNode *N = C.GenerateSink();
+    if (N) {
+      if (!BT_doubleclose)
+        BT_doubleclose = new BuiltinBug("Double fclose",
+                                        "Try to close a file Descriptor already"
+                                        " closed. Cause undefined behaviour.");
+      BugReport *R = new BugReport(*BT_doubleclose,
+                                   BT_doubleclose->getDescription(), N);
+      C.EmitReport(R);
+    }
+    return NULL;
+  }
+  
+  // Close the File Descriptor.
+  return state->set<StreamState>(Sym, StreamState::getClosed(CE));
+}
+
+void StreamChecker::EvalDeadSymbols(CheckerContext &C,SymbolReaper &SymReaper) {
+  for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
+         E = SymReaper.dead_end(); I != E; ++I) {
+    SymbolRef Sym = *I;
+    const GRState *state = C.getState();
+    const StreamState *SS = state->get<StreamState>(Sym);
+    if (!SS)
+      return;
+
+    if (SS->isOpened()) {
+      ExplodedNode *N = C.GenerateSink();
+      if (N) {
+        if (!BT_ResourceLeak)
+          BT_ResourceLeak = new BuiltinBug("Resource Leak", 
+                          "Opened File never closed. Potential Resource leak.");
+        BugReport *R = new BugReport(*BT_ResourceLeak, 
+                                     BT_ResourceLeak->getDescription(), N);
+        C.EmitReport(R);
+      }
+    }
+  }
+}
+
+void StreamChecker::EvalEndPath(GREndPathNodeBuilder &B, void *tag,
+                                GRExprEngine &Eng) {
+  SaveAndRestore<bool> OldHasGen(B.HasGeneratedNode);
+  const GRState *state = B.getState();
+  typedef llvm::ImmutableMap<SymbolRef, StreamState> SymMap;
+  SymMap M = state->get<StreamState>();
+  
+  for (SymMap::iterator I = M.begin(), E = M.end(); I != E; ++I) {
+    StreamState SS = I->second;
+    if (SS.isOpened()) {
+      ExplodedNode *N = B.generateNode(state, tag, B.getPredecessor());
+      if (N) {
+        if (!BT_ResourceLeak)
+          BT_ResourceLeak = new BuiltinBug("Resource Leak", 
+                          "Opened File never closed. Potential Resource leak.");
+        BugReport *R = new BugReport(*BT_ResourceLeak, 
+                                     BT_ResourceLeak->getDescription(), N);
+        Eng.getBugReporter().EmitReport(R);
+      }
+    }
+  }
+}
+
+void StreamChecker::PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S) {
+  const Expr *RetE = S->getRetValue();
+  if (!RetE)
+    return;
+  
+  const GRState *state = C.getState();
+  SymbolRef Sym = state->getSVal(RetE).getAsSymbol();
+  
+  if (!Sym)
+    return;
+  
+  const StreamState *SS = state->get<StreamState>(Sym);
+  if(!SS)
+    return;
+
+  if (SS->isOpened())
+    state = state->set<StreamState>(Sym, StreamState::getEscaped(S));
+
+  C.addTransition(state);
+}
diff --git a/lib/Checker/SymbolManager.cpp b/lib/Checker/SymbolManager.cpp
index c2b557e..3b1bb6d 100644
--- a/lib/Checker/SymbolManager.cpp
+++ b/lib/Checker/SymbolManager.cpp
@@ -28,22 +28,22 @@ static void print(llvm::raw_ostream& os, BinaryOperator::Opcode 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;
+    case BO_Mul: os << '*'  ; break;
+    case BO_Div: os << '/'  ; break;
+    case BO_Rem: os << '%'  ; break;
+    case BO_Add: os << '+'  ; break;
+    case BO_Sub: os << '-'  ; break;
+    case BO_Shl: os << "<<" ; break;
+    case BO_Shr: os << ">>" ; break;
+    case BO_LT:  os << "<"  ; break;
+    case BO_GT:  os << '>'  ; break;
+    case BO_LE:  os << "<=" ; break;
+    case BO_GE:  os << ">=" ; break;
+    case BO_EQ:  os << "==" ; break;
+    case BO_NE:  os << "!=" ; break;
+    case BO_And: os << '&'  ; break;
+    case BO_Xor: os << '^'  ; break;
+    case BO_Or:  os << '|'  ; break;
   }
 }
 
@@ -78,6 +78,11 @@ void SymbolExtent::dumpToStream(llvm::raw_ostream& os) const {
   os << "extent_$" << getSymbolID() << '{' << getRegion() << '}';
 }
 
+void SymbolMetadata::dumpToStream(llvm::raw_ostream& os) const {
+  os << "meta_$" << getSymbolID() << '{'
+     << getRegion() << ',' << T.getAsString() << '}';
+}
+
 void SymbolRegionValue::dumpToStream(llvm::raw_ostream& os) const {
   os << "reg_$" << getSymbolID() << "<" << R << ">";
 }
@@ -150,6 +155,24 @@ SymbolManager::getExtentSymbol(const SubRegion *R) {
   return cast<SymbolExtent>(SD);
 }
 
+const SymbolMetadata*
+SymbolManager::getMetadataSymbol(const MemRegion* R, const Stmt* S, QualType T,
+                                 unsigned Count, const void* SymbolTag) {
+
+  llvm::FoldingSetNodeID profile;
+  SymbolMetadata::Profile(profile, R, S, T, Count, SymbolTag);
+  void* InsertPos;
+  SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
+  if (!SD) {
+    SD = (SymExpr*) BPAlloc.Allocate<SymbolMetadata>();
+    new (SD) SymbolMetadata(SymbolCounter, R, S, T, Count, SymbolTag);
+    DataSet.InsertNode(SD, InsertPos);
+    ++SymbolCounter;
+  }
+
+  return cast<SymbolMetadata>(SD);
+}
+
 const SymIntExpr *SymbolManager::getSymIntExpr(const SymExpr *lhs,
                                                BinaryOperator::Opcode op,
                                                const llvm::APSInt& v,
@@ -191,21 +214,34 @@ QualType SymbolConjured::getType(ASTContext&) const {
 }
 
 QualType SymbolDerived::getType(ASTContext& Ctx) const {
-  return R->getValueType(Ctx);
+  return R->getValueType();
 }
 
 QualType SymbolExtent::getType(ASTContext& Ctx) const {
   return Ctx.getSizeType();
 }
 
+QualType SymbolMetadata::getType(ASTContext&) const {
+  return T;
+}
+
 QualType SymbolRegionValue::getType(ASTContext& C) const {
-  return R->getValueType(C);
+  return R->getValueType();
 }
 
 SymbolManager::~SymbolManager() {}
 
 bool SymbolManager::canSymbolicate(QualType T) {
-  return Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType());
+  if (Loc::IsLocType(T))
+    return true;
+
+  if (T->isIntegerType())
+    return T->isScalarType();
+
+  if (T->isRecordType())
+    return true;
+
+  return false;
 }
 
 void SymbolReaper::markLive(SymbolRef sym) {
@@ -213,6 +249,11 @@ void SymbolReaper::markLive(SymbolRef sym) {
   TheDead.erase(sym);
 }
 
+void SymbolReaper::markInUse(SymbolRef sym) {
+  if (isa<SymbolMetadata>(sym))
+    MetadataInUse.insert(sym);
+}
+
 bool SymbolReaper::maybeDead(SymbolRef sym) {
   if (isLive(sym))
     return false;
@@ -221,6 +262,31 @@ bool SymbolReaper::maybeDead(SymbolRef sym) {
   return true;
 }
 
+static bool IsLiveRegion(SymbolReaper &Reaper, const MemRegion *MR) {
+  MR = MR->getBaseRegion();
+
+  if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR))
+    return Reaper.isLive(SR->getSymbol());
+
+  if (const VarRegion *VR = dyn_cast<VarRegion>(MR))
+    return Reaper.isLive(VR);
+
+  // FIXME: This is a gross over-approximation. What we really need is a way to
+  // tell if anything still refers to this region. Unlike SymbolicRegions,
+  // AllocaRegions don't have associated symbols, though, so we don't actually
+  // have a way to track their liveness.
+  if (isa<AllocaRegion>(MR))
+    return true;
+
+  if (isa<CXXThisRegion>(MR))
+    return true;
+
+  if (isa<MemSpaceRegion>(MR))
+    return true;
+
+  return false;
+}
+
 bool SymbolReaper::isLive(SymbolRef sym) {
   if (TheLiving.count(sym))
     return true;
@@ -234,11 +300,21 @@ bool SymbolReaper::isLive(SymbolRef sym) {
   }
 
   if (const SymbolExtent *extent = dyn_cast<SymbolExtent>(sym)) {
-    const MemRegion *Base = extent->getRegion()->getBaseRegion();
-    if (const VarRegion *VR = dyn_cast<VarRegion>(Base))
-      return isLive(VR);
-    if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(Base))
-      return isLive(SR->getSymbol());
+    if (IsLiveRegion(*this, extent->getRegion())) {
+      markLive(sym);
+      return true;
+    }
+    return false;
+  }
+
+  if (const SymbolMetadata *metadata = dyn_cast<SymbolMetadata>(sym)) {
+    if (MetadataInUse.count(sym)) {
+      if (IsLiveRegion(*this, metadata->getRegion())) {
+        markLive(sym);
+        MetadataInUse.erase(sym);
+        return true;
+      }
+    }
     return false;
   }
 
@@ -248,16 +324,19 @@ bool SymbolReaper::isLive(SymbolRef sym) {
 }
 
 bool SymbolReaper::isLive(const Stmt* ExprVal) const {
-  return LCtx->getLiveVariables()->isLive(Loc, ExprVal);
+  return LCtx->getAnalysisContext()->getRelaxedLiveVariables()->
+      isLive(Loc, ExprVal);
 }
 
 bool SymbolReaper::isLive(const VarRegion *VR) const {
-  const StackFrameContext *SFC = VR->getStackFrame();
+  const StackFrameContext *VarContext = VR->getStackFrame();
+  const StackFrameContext *CurrentContext = LCtx->getCurrentStackFrame();
+
+  if (VarContext == CurrentContext)
+    return LCtx->getAnalysisContext()->getRelaxedLiveVariables()->
+        isLive(Loc, VR->getDecl());
 
-  if (SFC == LCtx->getCurrentStackFrame())
-    return LCtx->getLiveVariables()->isLive(Loc, VR->getDecl());
-  else
-    return SFC->isParentOf(LCtx->getCurrentStackFrame());
+  return VarContext->isParentOf(CurrentContext);
 }
 
 SymbolVisitor::~SymbolVisitor() {}
diff --git a/lib/Checker/UndefBranchChecker.cpp b/lib/Checker/UndefBranchChecker.cpp
index 9088345..1ff0641 100644
--- a/lib/Checker/UndefBranchChecker.cpp
+++ b/lib/Checker/UndefBranchChecker.cpp
@@ -29,27 +29,28 @@ class UndefBranchChecker : public Checker {
 
     FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
 
-    Expr* FindExpr(Expr* Ex) {
+    const Expr* FindExpr(const Expr* Ex) {
       if (!MatchesCriteria(Ex))
         return 0;
 
-      for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
-        if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
-          Expr* E2 = FindExpr(ExI);
+      for (Stmt::const_child_iterator I = Ex->child_begin(), 
+                                      E = Ex->child_end();I!=E;++I)
+        if (const Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
+          const Expr* E2 = FindExpr(ExI);
           if (E2) return E2;
         }
 
       return Ex;
     }
 
-    bool MatchesCriteria(Expr* Ex) { return St->getSVal(Ex).isUndef(); }
+    bool MatchesCriteria(const Expr* Ex) { return St->getSVal(Ex).isUndef(); }
   };
 
 public:
   UndefBranchChecker() : BT(0) {}
   static void *getTag();
   void VisitBranchCondition(GRBranchNodeBuilder &Builder, GRExprEngine &Eng,
-                            Stmt *Condition, void *tag);
+                            const Stmt *Condition, void *tag);
 };
 
 }
@@ -65,7 +66,7 @@ void *UndefBranchChecker::getTag() {
 
 void UndefBranchChecker::VisitBranchCondition(GRBranchNodeBuilder &Builder, 
                                               GRExprEngine &Eng,
-                                              Stmt *Condition, void *tag) {
+                                              const Stmt *Condition, void *tag){
   const GRState *state = Builder.getState();
   SVal X = state->getSVal(Condition);
   if (X.isUndef()) {
@@ -81,7 +82,7 @@ void UndefBranchChecker::VisitBranchCondition(GRBranchNodeBuilder &Builder,
       // subexpressions and roughly look for the most nested subexpression
       // that binds to Undefined.  We then highlight that expression's range.
       BlockEdge B = cast<BlockEdge>(N->getLocation());
-      Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
+      const Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
       assert (Ex && "Block must have a terminator.");
 
       // Get the predecessor node and check if is a PostStmt with the Stmt
diff --git a/lib/Checker/UndefinedAssignmentChecker.cpp b/lib/Checker/UndefinedAssignmentChecker.cpp
index 6cef60e..ccc9748 100644
--- a/lib/Checker/UndefinedAssignmentChecker.cpp
+++ b/lib/Checker/UndefinedAssignmentChecker.cpp
@@ -25,9 +25,8 @@ class UndefinedAssignmentChecker
 public:
   UndefinedAssignmentChecker() : BT(0) {}
   static void *getTag();
-  virtual void PreVisitBind(CheckerContext &C, const Stmt *AssignE,
-                            const Stmt *StoreE, SVal location,
-                            SVal val);
+  virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE,
+                            SVal location, SVal val);
 };
 }
 
@@ -41,7 +40,6 @@ void *UndefinedAssignmentChecker::getTag() {
 }
 
 void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C,
-                                              const Stmt *AssignE,
                                               const Stmt *StoreE,
                                               SVal location,
                                               SVal val) {
@@ -61,8 +59,8 @@ void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C,
   // Generate a report for this bug.
   const Expr *ex = 0;
 
-  while (AssignE) {
-    if (const BinaryOperator *B = dyn_cast<BinaryOperator>(AssignE)) {
+  while (StoreE) {
+    if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) {
       if (B->isCompoundAssignmentOp()) {
         const GRState *state = C.getState();
         if (state->getSVal(B->getLHS()).isUndef()) {
@@ -77,7 +75,7 @@ void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C,
       break;
     }
 
-    if (const DeclStmt *DS = dyn_cast<DeclStmt>(AssignE)) {
+    if (const DeclStmt *DS = dyn_cast<DeclStmt>(StoreE)) {
       const VarDecl* VD = dyn_cast<VarDecl>(DS->getSingleDecl());
       ex = VD->getInit();
     }
diff --git a/lib/Checker/UnixAPIChecker.cpp b/lib/Checker/UnixAPIChecker.cpp
index e9b8f09..de7346d 100644
--- a/lib/Checker/UnixAPIChecker.cpp
+++ b/lib/Checker/UnixAPIChecker.cpp
@@ -100,7 +100,7 @@ static void CheckOpen(CheckerContext &C, UnixAPIChecker &UC,
   NonLoc ocreateFlag =
     cast<NonLoc>(C.getValueManager().makeIntVal(UC.Val_O_CREAT.getValue(),
                                                 oflagsEx->getType()));
-  SVal maskedFlagsUC = C.getSValuator().EvalBinOpNN(state, BinaryOperator::And,
+  SVal maskedFlagsUC = C.getSValuator().EvalBinOpNN(state, BO_And,
                                                     oflags, ocreateFlag,
                                                     oflagsEx->getType());
   if (maskedFlagsUC.isUnknownOrUndef())
diff --git a/lib/Checker/UnreachableCodeChecker.cpp b/lib/Checker/UnreachableCodeChecker.cpp
new file mode 100644
index 0000000..7a56c7f
--- /dev/null
+++ b/lib/Checker/UnreachableCodeChecker.cpp
@@ -0,0 +1,226 @@
+//==- UnreachableCodeChecker.cpp - Generalized dead code checker -*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This file implements a generalized unreachable code checker using a
+// path-sensitive analysis. We mark any path visited, and then walk the CFG as a
+// post-analysis to determine what was never visited.
+//
+// A similar flow-sensitive only check exists in Analysis/ReachableCode.cpp
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ParentMap.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Checker/PathSensitive/CheckerVisitor.h"
+#include "clang/Checker/PathSensitive/ExplodedGraph.h"
+#include "clang/Checker/PathSensitive/SVals.h"
+#include "clang/Checker/PathSensitive/CheckerHelpers.h"
+#include "clang/Checker/BugReporter/BugReporter.h"
+#include "GRExprEngineExperimentalChecks.h"
+#include "llvm/ADT/SmallPtrSet.h"
+
+// The number of CFGBlock pointers we want to reserve memory for. This is used
+// once for each function we analyze.
+#define DEFAULT_CFGBLOCKS 256
+
+using namespace clang;
+
+namespace {
+class UnreachableCodeChecker : public CheckerVisitor<UnreachableCodeChecker> {
+public:
+  static void *getTag();
+  void VisitEndAnalysis(ExplodedGraph &G,
+                        BugReporter &B,
+                        GRExprEngine &Eng);
+private:
+  static inline const Stmt *getUnreachableStmt(const CFGBlock *CB);
+  void FindUnreachableEntryPoints(const CFGBlock *CB);
+  static bool isInvalidPath(const CFGBlock *CB, const ParentMap &PM);
+  static inline bool isEmptyCFGBlock(const CFGBlock *CB);
+
+  llvm::SmallSet<unsigned, DEFAULT_CFGBLOCKS> reachable;
+  llvm::SmallSet<unsigned, DEFAULT_CFGBLOCKS> visited;
+};
+}
+
+void *UnreachableCodeChecker::getTag() {
+  static int x = 0;
+  return &x;
+}
+
+void clang::RegisterUnreachableCodeChecker(GRExprEngine &Eng) {
+  Eng.registerCheck(new UnreachableCodeChecker());
+}
+
+void UnreachableCodeChecker::VisitEndAnalysis(ExplodedGraph &G,
+                                              BugReporter &B,
+                                              GRExprEngine &Eng) {
+  // Bail out if we didn't cover all paths
+  if (Eng.hasWorkRemaining())
+    return;
+
+  CFG *C = 0;
+  ParentMap *PM = 0;
+  // Iterate over ExplodedGraph
+  for (ExplodedGraph::node_iterator I = G.nodes_begin(), E = G.nodes_end();
+      I != E; ++I) {
+    const ProgramPoint &P = I->getLocation();
+    const LocationContext *LC = P.getLocationContext();
+
+    // Save the CFG if we don't have it already
+    if (!C)
+      C = LC->getAnalysisContext()->getUnoptimizedCFG();
+    if (!PM)
+      PM = &LC->getParentMap();
+
+    if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) {
+      const CFGBlock *CB = BE->getBlock();
+      reachable.insert(CB->getBlockID());
+    }
+  }
+
+  // Bail out if we didn't get the CFG or the ParentMap.
+  if (!C || !PM)
+    return;
+
+  ASTContext &Ctx = B.getContext();
+
+  // Find CFGBlocks that were not covered by any node
+  for (CFG::const_iterator I = C->begin(); I != C->end(); ++I) {
+    const CFGBlock *CB = *I;
+    // Check if the block is unreachable
+    if (reachable.count(CB->getBlockID()))
+      continue;
+
+    // Check if the block is empty (an artificial block)
+    if (isEmptyCFGBlock(CB))
+      continue;
+
+    // Find the entry points for this block
+    FindUnreachableEntryPoints(CB);
+
+    // This block may have been pruned; check if we still want to report it
+    if (reachable.count(CB->getBlockID()))
+      continue;
+
+    // Check for false positives
+    if (CB->size() > 0 && isInvalidPath(CB, *PM))
+      continue;
+
+    // Special case for __builtin_unreachable.
+    // FIXME: This should be extended to include other unreachable markers,
+    // such as llvm_unreachable.
+    if (!CB->empty()) {
+      const Stmt *First = CB->front();
+      if (const CallExpr *CE = dyn_cast<CallExpr>(First)) {
+        if (CE->isBuiltinCall(Ctx) == Builtin::BI__builtin_unreachable)
+          continue;
+      }
+    }
+
+    // We found a block that wasn't covered - find the statement to report
+    SourceRange SR;
+    SourceLocation SL;
+    if (const Stmt *S = getUnreachableStmt(CB)) {
+      SR = S->getSourceRange();
+      SL = S->getLocStart();
+      if (SR.isInvalid() || SL.isInvalid())
+        continue;
+    }
+    else
+      continue;
+
+    // Check if the SourceLocation is in a system header
+    const SourceManager &SM = B.getSourceManager();
+    if (SM.isInSystemHeader(SL) || SM.isInExternCSystemHeader(SL))
+      continue;
+
+    B.EmitBasicReport("Unreachable code", "Dead code", "This statement is never"
+        " executed", SL, SR);
+  }
+}
+
+// Recursively finds the entry point(s) for this dead CFGBlock.
+void UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB) {
+  bool allPredecessorsReachable = true;
+
+  visited.insert(CB->getBlockID());
+
+  for (CFGBlock::const_pred_iterator I = CB->pred_begin(); I != CB->pred_end();
+      ++I) {
+    // Recurse over all unreachable blocks
+    if (!reachable.count((*I)->getBlockID())) {
+      // At least one predeccessor was unreachable
+      allPredecessorsReachable = false;
+
+      // Only visit the block once
+      if (!visited.count((*I)->getBlockID()))
+        FindUnreachableEntryPoints(*I);
+    }
+  }
+
+  // If at least one predecessor is unreachable, mark this block as reachable
+  // so we don't report this block.
+  if (!allPredecessorsReachable) {
+    reachable.insert(CB->getBlockID());
+  }
+}
+
+// Find the Stmt* in a CFGBlock for reporting a warning
+const Stmt *UnreachableCodeChecker::getUnreachableStmt(const CFGBlock *CB) {
+  if (CB->size() > 0)
+    return CB->front().getStmt();
+  else if (const Stmt *S = CB->getTerminator())
+    return S;
+  else
+    return 0;
+}
+
+// Determines if the path to this CFGBlock contained an element that infers this
+// block is a false positive. We assume that FindUnreachableEntryPoints has
+// already marked only the entry points to any dead code, so we need only to
+// find the condition that led to this block (the predecessor of this block.)
+// There will never be more than one predecessor.
+bool UnreachableCodeChecker::isInvalidPath(const CFGBlock *CB,
+                                           const ParentMap &PM) {
+  // We only expect a predecessor size of 0 or 1. If it is >1, then an external
+  // condition has broken our assumption (for example, a sink being placed by
+  // another check). In these cases, we choose not to report.
+  if (CB->pred_size() > 1)
+    return true;
+
+  // If there are no predecessors, then this block is trivially unreachable
+  if (CB->pred_size() == 0)
+    return false;
+
+  const CFGBlock *pred = *CB->pred_begin();
+
+  // Get the predecessor block's terminator conditon
+  const Stmt *cond = pred->getTerminatorCondition();
+
+  //assert(cond && "CFGBlock's predecessor has a terminator condition");
+  // The previous assertion is invalid in some cases (eg do/while). Leaving
+  // reporting of these situations on at the moment to help triage these cases.
+  if (!cond)
+    return false;
+
+  // Run each of the checks on the conditions
+  if (containsMacro(cond) || containsEnum(cond)
+      || containsStaticLocal(cond) || containsBuiltinOffsetOf(cond)
+      || containsStmt<SizeOfAlignOfExpr>(cond))
+    return true;
+
+  return false;
+}
+
+// Returns true if the given CFGBlock is empty
+bool UnreachableCodeChecker::isEmptyCFGBlock(const CFGBlock *CB) {
+  return CB->getLabel() == 0       // No labels
+      && CB->size() == 0           // No statements
+      && CB->getTerminator() == 0; // No terminator
+}
diff --git a/lib/Checker/VLASizeChecker.cpp b/lib/Checker/VLASizeChecker.cpp
index 936991d..0800b8b 100644
--- a/lib/Checker/VLASizeChecker.cpp
+++ b/lib/Checker/VLASizeChecker.cpp
@@ -117,7 +117,7 @@ void VLASizeChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) {
   SVal EleSizeVal = ValMgr.makeIntVal(EleSize.getQuantity(), SizeTy);
 
   // Multiply the array length by the element size.
-  SVal ArraySizeVal = SV.EvalBinOpNN(state, BinaryOperator::Mul, ArrayLength,
+  SVal ArraySizeVal = SV.EvalBinOpNN(state, BO_Mul, ArrayLength,
                                      cast<NonLoc>(EleSizeVal), SizeTy);
 
   // Finally, Assume that the array's extent matches the given size.
diff --git a/lib/Checker/ValueManager.cpp b/lib/Checker/ValueManager.cpp
index aa0c3c8..8b7cd7b 100644
--- a/lib/Checker/ValueManager.cpp
+++ b/lib/Checker/ValueManager.cpp
@@ -72,7 +72,7 @@ SVal ValueManager::convertToArrayIndex(SVal V) {
 
 DefinedOrUnknownSVal 
 ValueManager::getRegionValueSymbolVal(const TypedRegion* R) {
-  QualType T = R->getValueType(SymMgr.getContext());
+  QualType T = R->getValueType();
 
   if (!SymbolManager::canSymbolicate(T))
     return UnknownVal();
@@ -117,11 +117,24 @@ DefinedOrUnknownSVal ValueManager::getConjuredSymbolVal(const void *SymbolTag,
   return nonloc::SymbolVal(sym);
 }
 
+DefinedSVal ValueManager::getMetadataSymbolVal(const void *SymbolTag,
+                                               const MemRegion *MR,
+                                               const Expr *E, QualType T,
+                                               unsigned Count) {
+  assert(SymbolManager::canSymbolicate(T) && "Invalid metadata symbol type");
+
+  SymbolRef sym = SymMgr.getMetadataSymbol(MR, E, T, Count, SymbolTag);
+
+  if (Loc::IsLocType(T))
+    return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
+
+  return nonloc::SymbolVal(sym);
+}
 
 DefinedOrUnknownSVal
 ValueManager::getDerivedRegionValueSymbolVal(SymbolRef parentSymbol,
                                              const TypedRegion *R) {
-  QualType T = R->getValueType(R->getContext());
+  QualType T = R->getValueType();
 
   if (!SymbolManager::canSymbolicate(T))
     return UnknownVal();
-- 
cgit v1.1