From b6d5e15aae202f157c6cd63da8fa4b089e7b31e9 Mon Sep 17 00:00:00 2001
From: rdivacky <rdivacky@FreeBSD.org>
Date: Wed, 4 Nov 2009 15:04:32 +0000
Subject: Update clang to r86025.

---
 lib/Analysis/AttrNonNullChecker.cpp         | 100 +++++++
 lib/Analysis/BadCallChecker.cpp             |  44 ++++
 lib/Analysis/BasicObjCFoundationChecks.cpp  |   1 +
 lib/Analysis/BasicObjCFoundationChecks.h    |   1 +
 lib/Analysis/BasicStore.cpp                 |  26 +-
 lib/Analysis/CFRefCount.cpp                 |  34 +--
 lib/Analysis/CMakeLists.txt                 |  10 +-
 lib/Analysis/CallGraph.cpp                  |   4 +-
 lib/Analysis/CheckNSError.cpp               | 238 -----------------
 lib/Analysis/CheckObjCUnusedIVars.cpp       |  35 ++-
 lib/Analysis/DereferenceChecker.cpp         | 112 ++++++++
 lib/Analysis/DivZeroChecker.cpp             |  70 +++++
 lib/Analysis/GRExprEngine.cpp               | 391 +++++++++++++---------------
 lib/Analysis/GRExprEngineInternalChecks.cpp | 390 ++-------------------------
 lib/Analysis/NSAutoreleasePoolChecker.cpp   |  84 ++++++
 lib/Analysis/NSErrorChecker.cpp             | 241 +++++++++++++++++
 lib/Analysis/RegionStore.cpp                |  39 ++-
 lib/Analysis/UndefinedArgChecker.cpp        |  43 +++
 lib/Analysis/UndefinedAssignmentChecker.cpp |  61 +++++
 lib/Analysis/VLASizeChecker.cpp             | 102 ++++++++
 20 files changed, 1152 insertions(+), 874 deletions(-)
 create mode 100644 lib/Analysis/AttrNonNullChecker.cpp
 create mode 100644 lib/Analysis/BadCallChecker.cpp
 delete mode 100644 lib/Analysis/CheckNSError.cpp
 create mode 100644 lib/Analysis/DereferenceChecker.cpp
 create mode 100644 lib/Analysis/DivZeroChecker.cpp
 create mode 100644 lib/Analysis/NSAutoreleasePoolChecker.cpp
 create mode 100644 lib/Analysis/NSErrorChecker.cpp
 create mode 100644 lib/Analysis/UndefinedArgChecker.cpp
 create mode 100644 lib/Analysis/UndefinedAssignmentChecker.cpp
 create mode 100644 lib/Analysis/VLASizeChecker.cpp

(limited to 'lib/Analysis')

diff --git a/lib/Analysis/AttrNonNullChecker.cpp b/lib/Analysis/AttrNonNullChecker.cpp
new file mode 100644
index 0000000..1cf5d0c
--- /dev/null
+++ b/lib/Analysis/AttrNonNullChecker.cpp
@@ -0,0 +1,100 @@
+//===--- AttrNonNullChecker.h - Undefined arguments checker ----*- C++ -*--===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines AttrNonNullChecker, a builtin check in GRExprEngine that 
+// performs checks for arguments declared to have nonnull attribute.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+
+using namespace clang;
+
+void *AttrNonNullChecker::getTag() {
+  static int x = 0;
+  return &x;
+}
+
+void AttrNonNullChecker::PreVisitCallExpr(CheckerContext &C, 
+                                          const CallExpr *CE) {
+  const GRState *state = C.getState();
+  const GRState *originalState = state;
+
+  // Check if the callee has a 'nonnull' attribute.
+  SVal X = state->getSVal(CE->getCallee());
+
+  const FunctionDecl* FD = X.getAsFunctionDecl();
+  if (!FD)
+    return;
+
+  const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
+  if (!Att)
+    return;
+
+  // Iterate through the arguments of CE and check them for null.
+  unsigned idx = 0;
+
+  for (CallExpr::const_arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
+       ++I, ++idx) {
+
+    if (!Att->isNonNull(idx))
+      continue;
+
+    const SVal &V = state->getSVal(*I);
+    const DefinedSVal *DV = dyn_cast<DefinedSVal>(&V);
+
+    if (!DV)
+      continue;
+
+    ConstraintManager &CM = C.getConstraintManager();
+    const GRState *stateNotNull, *stateNull;
+    llvm::tie(stateNotNull, stateNull) = CM.AssumeDual(state, *DV);
+
+    if (stateNull && !stateNotNull) {
+      // Generate an error node.  Check for a null node in case
+      // we cache out.
+      if (ExplodedNode *errorNode = C.GenerateNode(CE, stateNull, true)) {
+
+        // Lazily allocate the BugType object if it hasn't already been
+        // created. Ownership is transferred to the BugReporter object once
+        // the BugReport is passed to 'EmitWarning'.
+        if (!BT)
+          BT = new BugType("Argument with 'nonnull' attribute passed null",
+                           "API");
+
+        EnhancedBugReport *R =
+          new EnhancedBugReport(*BT,
+                                "Null pointer passed as an argument to a "
+                                "'nonnull' parameter", errorNode);
+
+        // Highlight the range of the argument that was null.
+        const Expr *arg = *I;
+        R->addRange(arg->getSourceRange());
+        R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, arg);
+
+        // Emit the bug report.
+        C.EmitReport(R);
+      }
+
+      // Always return.  Either we cached out or we just emitted an error.
+      return;
+    }
+
+    // If a pointer value passed the check we should assume that it is
+    // indeed not null from this point forward.
+    assert(stateNotNull);
+    state = stateNotNull;
+  }
+
+  // If we reach here all of the arguments passed the nonnull check.
+  // If 'state' has been updated generated a new node.
+  if (state != originalState)
+    C.addTransition(C.GenerateNode(CE, state));
+}
diff --git a/lib/Analysis/BadCallChecker.cpp b/lib/Analysis/BadCallChecker.cpp
new file mode 100644
index 0000000..33bb515
--- /dev/null
+++ b/lib/Analysis/BadCallChecker.cpp
@@ -0,0 +1,44 @@
+//===--- BadCallChecker.h - Bad call checker --------------------*- C++ -*--==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines BadCallChecker, a builtin check in GRExprEngine that performs
+// checks for bad callee at call sites.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checkers/BadCallChecker.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+
+using namespace clang;
+
+void *BadCallChecker::getTag() {
+  static int x = 0;
+  return &x;
+}
+
+void BadCallChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
+  const Expr *Callee = CE->getCallee()->IgnoreParens();
+  SVal L = C.getState()->getSVal(Callee);
+
+  if (L.isUndef() || isa<loc::ConcreteInt>(L)) {
+    if (ExplodedNode *N = C.GenerateNode(CE, true)) {
+      if (!BT)
+        BT = new BuiltinBug(0, "Invalid function call",
+                "Called function pointer is a null or undefined pointer value");
+
+      EnhancedBugReport *R =
+        new EnhancedBugReport(*BT, BT->getDescription().c_str(), N);
+        
+      R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+                           bugreporter::GetCalleeExpr(N));
+
+      C.EmitReport(R);
+    }
+  }
+}
diff --git a/lib/Analysis/BasicObjCFoundationChecks.cpp b/lib/Analysis/BasicObjCFoundationChecks.cpp
index aa2d0ab..4781d5e 100644
--- a/lib/Analysis/BasicObjCFoundationChecks.cpp
+++ b/lib/Analysis/BasicObjCFoundationChecks.cpp
@@ -535,4 +535,5 @@ void clang::RegisterAppleChecks(GRExprEngine& Eng, const Decl &D) {
   Eng.AddCheck(CreateAuditCFRetainRelease(Ctx, BR), Stmt::CallExprClass);
 
   RegisterNSErrorChecks(BR, Eng, D);
+  RegisterNSAutoreleasePoolChecks(Eng);
 }
diff --git a/lib/Analysis/BasicObjCFoundationChecks.h b/lib/Analysis/BasicObjCFoundationChecks.h
index 1271ae4..ea4d3ec 100644
--- a/lib/Analysis/BasicObjCFoundationChecks.h
+++ b/lib/Analysis/BasicObjCFoundationChecks.h
@@ -42,6 +42,7 @@ GRSimpleAPICheck *CreateAuditCFRetainRelease(ASTContext& Ctx,
                                              BugReporter& BR);
 
 void RegisterNSErrorChecks(BugReporter& BR, GRExprEngine &Eng, const Decl &D);
+void RegisterNSAutoreleasePoolChecks(GRExprEngine &Eng);
 
 } // end clang namespace
 
diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp
index d81d83c..888af9b 100644
--- a/lib/Analysis/BasicStore.cpp
+++ b/lib/Analysis/BasicStore.cpp
@@ -92,19 +92,17 @@ public:
 
   void iterBindings(Store store, BindingsHandler& f);
 
-  const GRState *BindDecl(const GRState *state, const VarDecl *VD,
-                          const LocationContext *LC, SVal InitVal) {
-    return state->makeWithStore(BindDeclInternal(state->getStore(),VD, LC,
+  const GRState *BindDecl(const GRState *state, const VarRegion *VR,
+                          SVal InitVal) {
+    return state->makeWithStore(BindDeclInternal(state->getStore(), VR,
                                                  &InitVal));
   }
 
-  const GRState *BindDeclWithNoInit(const GRState *state, const VarDecl *VD,
-                                    const LocationContext *LC) {
-    return state->makeWithStore(BindDeclInternal(state->getStore(), VD, LC, 0));
+  const GRState *BindDeclWithNoInit(const GRState *state, const VarRegion *VR) {
+    return state->makeWithStore(BindDeclInternal(state->getStore(), VR, 0));
   }
 
-  Store BindDeclInternal(Store store, const VarDecl *VD,
-                         const LocationContext *LC, SVal *InitVal);
+  Store BindDeclInternal(Store store, const VarRegion *VR, SVal *InitVal);
 
   static inline BindingsTy GetBindings(Store store) {
     return BindingsTy(static_cast<const BindingsTy::TreeTy*>(store));
@@ -532,11 +530,11 @@ Store BasicStoreManager::getInitialStore(const LocationContext *InitLoc) {
   return St;
 }
 
-Store BasicStoreManager::BindDeclInternal(Store store, const VarDecl* VD,
-                                          const LocationContext *LC,
+Store BasicStoreManager::BindDeclInternal(Store store, const VarRegion* VR,
                                           SVal* InitVal) {
 
   BasicValueFactory& BasicVals = StateMgr.getBasicVals();
+  const VarDecl *VD = VR->getDecl();
 
   // BasicStore does not model arrays and structs.
   if (VD->getType()->isArrayType() || VD->getType()->isStructureType())
@@ -564,16 +562,16 @@ Store BasicStoreManager::BindDeclInternal(Store store, const VarDecl* VD,
       if (!InitVal) {
         QualType T = VD->getType();
         if (Loc::IsLocType(T))
-          store = BindInternal(store, getLoc(VD, LC),
+          store = BindInternal(store, loc::MemRegionVal(VR),
                        loc::ConcreteInt(BasicVals.getValue(0, T)));
         else if (T->isIntegerType())
-          store = BindInternal(store, getLoc(VD, LC),
+          store = BindInternal(store, loc::MemRegionVal(VR),
                        nonloc::ConcreteInt(BasicVals.getValue(0, T)));
         else {
           // assert(0 && "ignore other types of variables");
         }
       } else {
-        store = BindInternal(store, getLoc(VD, LC), *InitVal);
+        store = BindInternal(store, loc::MemRegionVal(VR), *InitVal);
       }
     }
   } else {
@@ -581,7 +579,7 @@ Store BasicStoreManager::BindDeclInternal(Store store, const VarDecl* VD,
     QualType T = VD->getType();
     if (ValMgr.getSymbolManager().canSymbolicate(T)) {
       SVal V = InitVal ? *InitVal : UndefinedVal();
-      store = BindInternal(store, getLoc(VD, LC), V);
+      store = BindInternal(store, loc::MemRegionVal(VR), V);
     }
   }
 
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index c629ad1..03614e8 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -193,20 +193,6 @@ public:
 } // end anonymous namespace
 
 //===----------------------------------------------------------------------===//
-// Selector creation functions.
-//===----------------------------------------------------------------------===//
-
-static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) {
-  IdentifierInfo* II = &Ctx.Idents.get(name);
-  return Ctx.Selectors.getSelector(0, &II);
-}
-
-static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
-  IdentifierInfo* II = &Ctx.Idents.get(name);
-  return Ctx.Selectors.getSelector(1, &II);
-}
-
-//===----------------------------------------------------------------------===//
 // Type querying functions.
 //===----------------------------------------------------------------------===//
 
@@ -1031,11 +1017,25 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
           // Eventually this can be improved by recognizing that the pixel
           // buffer passed to CVPixelBufferCreateWithBytes is released via
           // a callback and doing full IPA to make sure this is done correctly.
+          // FIXME: This function has an out parameter that returns an
+          // allocated object.
           ScratchArgs = AF.Add(ScratchArgs, 7, StopTracking);
           S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing,
                                    DoNothing);
         }
         break;
+        
+      case 29:
+        if (!memcmp(FName, "CGBitmapContextCreateWithData", 29)) {
+          // FIXES: <rdar://problem/7358899>
+          // Eventually this can be improved by recognizing that 'releaseInfo'
+          // passed to CGBitmapContextCreateWithData is released via
+          // a callback and doing full IPA to make sure this is done correctly.
+          ScratchArgs = AF.Add(ScratchArgs, 8, StopTracking);
+          S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
+                                   DoNothing,DoNothing);          
+        }
+        break;
 
       case 32:
         if (!memcmp(FName, "IOServiceAddMatchingNotification", 32)) {
@@ -1899,7 +1899,7 @@ public:
 
   virtual ~CFRefCount() {}
 
-  void RegisterChecks(BugReporter &BR);
+  void RegisterChecks(GRExprEngine &Eng);
 
   virtual void RegisterPrinters(std::vector<GRState::Printer*>& Printers) {
     Printers.push_back(new BindingsPrinter());
@@ -2193,7 +2193,9 @@ namespace {
   };
 } // end anonymous namespace
 
-void CFRefCount::RegisterChecks(BugReporter& BR) {
+void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
+  BugReporter &BR = Eng.getBugReporter();
+  
   useAfterRelease = new UseAfterRelease(this);
   BR.Register(useAfterRelease);
 
diff --git a/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt
index 89c1783..cd4697f 100644
--- a/lib/Analysis/CMakeLists.txt
+++ b/lib/Analysis/CMakeLists.txt
@@ -3,6 +3,8 @@ set(LLVM_NO_RTTI 1)
 add_clang_library(clangAnalysis
   AnalysisContext.cpp
   AnalysisManager.cpp
+  AttrNonNullChecker.cpp
+  BadCallChecker.cpp
   BasicConstraintManager.cpp
   BasicObjCFoundationChecks.cpp
   BasicStore.cpp
@@ -14,11 +16,12 @@ add_clang_library(clangAnalysis
   CallGraph.cpp
   CallInliner.cpp
   CheckDeadStores.cpp
-  CheckNSError.cpp
   CheckObjCDealloc.cpp
   CheckObjCInstMethSignature.cpp
   CheckObjCUnusedIVars.cpp
   CheckSecuritySyntaxOnly.cpp
+  DereferenceChecker.cpp
+  DivZeroChecker.cpp
   Environment.cpp
   ExplodedGraph.cpp
   GRBlockCounter.cpp
@@ -28,6 +31,8 @@ add_clang_library(clangAnalysis
   GRState.cpp
   LiveVariables.cpp
   MemRegion.cpp
+  NSAutoreleasePoolChecker.cpp
+  NSErrorChecker.cpp
   PathDiagnostic.cpp
   RangeConstraintManager.cpp
   RegionStore.cpp
@@ -37,8 +42,11 @@ add_clang_library(clangAnalysis
   SimpleSValuator.cpp
   Store.cpp
   SymbolManager.cpp
+  UndefinedArgChecker.cpp
+  UndefinedAssignmentChecker.cpp
   UninitializedValues.cpp
   ValueManager.cpp
+  VLASizeChecker.cpp
   )
 
 add_dependencies(clangAnalysis ClangDiagnosticAnalysis)
diff --git a/lib/Analysis/CallGraph.cpp b/lib/Analysis/CallGraph.cpp
index ae8845d..17dc068 100644
--- a/lib/Analysis/CallGraph.cpp
+++ b/lib/Analysis/CallGraph.cpp
@@ -68,10 +68,8 @@ CallGraph::~CallGraph() {
   }
 }
 
-void CallGraph::addTU(ASTUnit &AST) {
-  ASTContext &Ctx = AST.getASTContext();
+void CallGraph::addTU(ASTContext& Ctx) {
   DeclContext *DC = Ctx.getTranslationUnitDecl();
-
   for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
        I != E; ++I) {
 
diff --git a/lib/Analysis/CheckNSError.cpp b/lib/Analysis/CheckNSError.cpp
deleted file mode 100644
index 8086da5..0000000
--- a/lib/Analysis/CheckNSError.cpp
+++ /dev/null
@@ -1,238 +0,0 @@
-//=- CheckNSError.cpp - Coding conventions for uses of NSError ---*- 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 a CheckNSError, a flow-insenstive check
-//  that determines if an Objective-C class interface correctly returns
-//  a non-void return type.
-//
-//  File under feature request PR 2600.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Analysis/LocalCheckers.h"
-#include "clang/Analysis/PathSensitive/BugReporter.h"
-#include "clang/Analysis/PathSensitive/GRExprEngine.h"
-#include "BasicObjCFoundationChecks.h"
-#include "llvm/Support/Compiler.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/Decl.h"
-#include "llvm/ADT/SmallVector.h"
-
-using namespace clang;
-
-namespace {
-class VISIBILITY_HIDDEN NSErrorCheck : public BugType {
-  const Decl &CodeDecl;
-  const bool isNSErrorWarning;
-  IdentifierInfo * const II;
-  GRExprEngine &Eng;
-
-  void CheckSignature(const ObjCMethodDecl& MD, QualType& ResultTy,
-                      llvm::SmallVectorImpl<VarDecl*>& ErrorParams);
-
-  void CheckSignature(const FunctionDecl& MD, QualType& ResultTy,
-                      llvm::SmallVectorImpl<VarDecl*>& ErrorParams);
-
-  bool CheckNSErrorArgument(QualType ArgTy);
-  bool CheckCFErrorArgument(QualType ArgTy);
-
-  void CheckParamDeref(const VarDecl *V, const LocationContext *LC,
-                       const GRState *state, BugReporter& BR);
-
-  void EmitRetTyWarning(BugReporter& BR, const Decl& CodeDecl);
-
-public:
-  NSErrorCheck(const Decl &D, bool isNSError, GRExprEngine& eng)
-    : BugType(isNSError ? "NSError** null dereference"
-                        : "CFErrorRef* null dereference",
-              "Coding conventions (Apple)"),
-    CodeDecl(D),
-    isNSErrorWarning(isNSError),
-    II(&eng.getContext().Idents.get(isNSErrorWarning ? "NSError":"CFErrorRef")),
-    Eng(eng) {}
-
-  void FlushReports(BugReporter& BR);
-};
-
-} // end anonymous namespace
-
-void clang::RegisterNSErrorChecks(BugReporter& BR, GRExprEngine &Eng,
-                                  const Decl &D) {
-  BR.Register(new NSErrorCheck(D, true, Eng));
-  BR.Register(new NSErrorCheck(D, false, Eng));
-}
-
-void NSErrorCheck::FlushReports(BugReporter& BR) {
-  // Get the analysis engine and the exploded analysis graph.
-  ExplodedGraph& G = Eng.getGraph();
-
-  // Get the ASTContext, which is useful for querying type information.
-  ASTContext &Ctx = BR.getContext();
-
-  QualType ResultTy;
-  llvm::SmallVector<VarDecl*, 5> ErrorParams;
-
-  if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(&CodeDecl))
-    CheckSignature(*MD, ResultTy, ErrorParams);
-  else if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(&CodeDecl))
-    CheckSignature(*FD, ResultTy, ErrorParams);
-  else
-    return;
-
-  if (ErrorParams.empty())
-    return;
-
-  if (ResultTy == Ctx.VoidTy) EmitRetTyWarning(BR, CodeDecl);
-
-  for (ExplodedGraph::roots_iterator RI=G.roots_begin(), RE=G.roots_end();
-       RI!=RE; ++RI) {
-    // Scan the parameters for an implicit null dereference.
-    for (llvm::SmallVectorImpl<VarDecl*>::iterator I=ErrorParams.begin(),
-          E=ErrorParams.end(); I!=E; ++I)
-        CheckParamDeref(*I, (*RI)->getLocationContext(), (*RI)->getState(), BR);
-  }
-}
-
-void NSErrorCheck::EmitRetTyWarning(BugReporter& BR, const Decl& CodeDecl) {
-  std::string sbuf;
-  llvm::raw_string_ostream os(sbuf);
-
-  if (isa<ObjCMethodDecl>(CodeDecl))
-    os << "Method";
-  else
-    os << "Function";
-
-  os << " accepting ";
-  os << (isNSErrorWarning ? "NSError**" : "CFErrorRef*");
-  os << " should have a non-void return value to indicate whether or not an "
-        "error occurred";
-
-  BR.EmitBasicReport(isNSErrorWarning
-                     ? "Bad return type when passing NSError**"
-                     : "Bad return type when passing CFError*",
-                     getCategory().c_str(), os.str().c_str(),
-                     CodeDecl.getLocation());
-}
-
-void
-NSErrorCheck::CheckSignature(const ObjCMethodDecl& M, QualType& ResultTy,
-                             llvm::SmallVectorImpl<VarDecl*>& ErrorParams) {
-
-  ResultTy = M.getResultType();
-
-  for (ObjCMethodDecl::param_iterator I=M.param_begin(),
-       E=M.param_end(); I!=E; ++I)  {
-
-    QualType T = (*I)->getType();
-
-    if (isNSErrorWarning) {
-      if (CheckNSErrorArgument(T)) ErrorParams.push_back(*I);
-    }
-    else if (CheckCFErrorArgument(T))
-      ErrorParams.push_back(*I);
-  }
-}
-
-void
-NSErrorCheck::CheckSignature(const FunctionDecl& F, QualType& ResultTy,
-                             llvm::SmallVectorImpl<VarDecl*>& ErrorParams) {
-
-  ResultTy = F.getResultType();
-
-  for (FunctionDecl::param_const_iterator I = F.param_begin(),
-                                          E = F.param_end(); I != E; ++I)  {
-
-    QualType T = (*I)->getType();
-
-    if (isNSErrorWarning) {
-      if (CheckNSErrorArgument(T)) ErrorParams.push_back(*I);
-    }
-    else if (CheckCFErrorArgument(T))
-      ErrorParams.push_back(*I);
-  }
-}
-
-
-bool NSErrorCheck::CheckNSErrorArgument(QualType ArgTy) {
-
-  const PointerType* PPT = ArgTy->getAs<PointerType>();
-  if (!PPT)
-    return false;
-
-  const ObjCObjectPointerType* PT =
-    PPT->getPointeeType()->getAs<ObjCObjectPointerType>();
-
-  if (!PT)
-    return false;
-
-  const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
-
-  // FIXME: Can ID ever be NULL?
-  if (ID)
-    return II == ID->getIdentifier();
-
-  return false;
-}
-
-bool NSErrorCheck::CheckCFErrorArgument(QualType ArgTy) {
-
-  const PointerType* PPT = ArgTy->getAs<PointerType>();
-  if (!PPT) return false;
-
-  const TypedefType* TT = PPT->getPointeeType()->getAs<TypedefType>();
-  if (!TT) return false;
-
-  return TT->getDecl()->getIdentifier() == II;
-}
-
-void NSErrorCheck::CheckParamDeref(const VarDecl *Param,
-                                   const LocationContext *LC,
-                                   const GRState *rootState,
-                                   BugReporter& BR) {
-
-  SVal ParamL = rootState->getLValue(Param, LC);
-  const MemRegion* ParamR = cast<loc::MemRegionVal>(ParamL).getRegionAs<VarRegion>();
-  assert (ParamR && "Parameters always have VarRegions.");
-  SVal ParamSVal = rootState->getSVal(ParamR);
-
-  // FIXME: For now assume that ParamSVal is symbolic.  We need to generalize
-  // this later.
-  SymbolRef ParamSym = ParamSVal.getAsLocSymbol();
-  if (!ParamSym)
-    return;
-
-  // Iterate over the implicit-null dereferences.
-  for (GRExprEngine::null_deref_iterator I=Eng.implicit_null_derefs_begin(),
-       E=Eng.implicit_null_derefs_end(); I!=E; ++I) {
-
-    const GRState *state = (*I)->getState();
-    const SVal* X = state->get<GRState::NullDerefTag>();
-
-    if (!X || X->getAsSymbol() != ParamSym)
-      continue;
-
-    // Emit an error.
-    std::string sbuf;
-    llvm::raw_string_ostream os(sbuf);
-      os << "Potential null dereference.  According to coding standards ";
-
-    if (isNSErrorWarning)
-      os << "in 'Creating and Returning NSError Objects' the parameter '";
-    else
-      os << "documented in CoreFoundation/CFError.h the parameter '";
-
-    os << Param->getNameAsString() << "' may be null.";
-
-    BugReport *report = new BugReport(*this, os.str().c_str(), *I);
-    // FIXME: Notable symbols are now part of the report.  We should
-    //  add support for notable symbols in BugReport.
-    //    BR.addNotableSymbol(SV->getSymbol());
-    BR.EmitReport(report);
-  }
-}
diff --git a/lib/Analysis/CheckObjCUnusedIVars.cpp b/lib/Analysis/CheckObjCUnusedIVars.cpp
index 1a900f8..2d9b531 100644
--- a/lib/Analysis/CheckObjCUnusedIVars.cpp
+++ b/lib/Analysis/CheckObjCUnusedIVars.cpp
@@ -62,6 +62,29 @@ static void Scan(IvarUsageMap& M, const ObjCPropertyImplDecl* D) {
     I->second = Used;
 }
 
+static void Scan(IvarUsageMap& M, const ObjCContainerDecl* D) {
+  // Scan the methods for accesses.
+  for (ObjCContainerDecl::instmeth_iterator I = D->instmeth_begin(),
+       E = D->instmeth_end(); I!=E; ++I)
+    Scan(M, (*I)->getBody());
+  
+  if (const ObjCImplementationDecl *ID = dyn_cast<ObjCImplementationDecl>(D)) {    
+    // Scan for @synthesized property methods that act as setters/getters
+    // to an ivar.
+    for (ObjCImplementationDecl::propimpl_iterator I = ID->propimpl_begin(),
+         E = ID->propimpl_end(); I!=E; ++I)
+      Scan(M, *I);
+    
+    // Scan the associated categories as well.
+    for (const ObjCCategoryDecl *CD =
+          ID->getClassInterface()->getCategoryList(); CD ;
+          CD = CD->getNextClassCategory()) {
+      if (const ObjCCategoryImplDecl *CID = CD->getImplementation())
+        Scan(M, CID);
+    }
+  }
+}
+
 void clang::CheckObjCUnusedIvar(const ObjCImplementationDecl *D,
                                 BugReporter &BR) {
 
@@ -88,16 +111,8 @@ void clang::CheckObjCUnusedIvar(const ObjCImplementationDecl *D,
   if (M.empty())
     return;
 
-  // Now scan the methods for accesses.
-  for (ObjCImplementationDecl::instmeth_iterator I = D->instmeth_begin(),
-        E = D->instmeth_end(); I!=E; ++I)
-    Scan(M, (*I)->getBody());
-
-  // Scan for @synthesized property methods that act as setters/getters
-  // to an ivar.
-  for (ObjCImplementationDecl::propimpl_iterator I = D->propimpl_begin(),
-       E = D->propimpl_end(); I!=E; ++I)
-    Scan(M, *I);
+  // Now scan the implementation declaration.
+  Scan(M, D);
 
   // Find ivars that are unused.
   for (IvarUsageMap::iterator I = M.begin(), E = M.end(); I!=E; ++I)
diff --git a/lib/Analysis/DereferenceChecker.cpp b/lib/Analysis/DereferenceChecker.cpp
new file mode 100644
index 0000000..33c85d5
--- /dev/null
+++ b/lib/Analysis/DereferenceChecker.cpp
@@ -0,0 +1,112 @@
+//== NullDerefChecker.cpp - Null dereference checker ------------*- C++ -*--==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines NullDerefChecker, a builtin check in GRExprEngine that performs
+// checks for null pointers at loads and stores.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h"
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+
+using namespace clang;
+
+void *NullDerefChecker::getTag() {
+  static int x = 0;
+  return &x;
+}
+
+ExplodedNode *NullDerefChecker::CheckLocation(const Stmt *S, ExplodedNode *Pred,
+                                              const GRState *state, SVal V,
+                                              GRExprEngine &Eng) {
+  Loc *LV = dyn_cast<Loc>(&V);
+  
+    // If the value is not a location, don't touch the node.
+  if (!LV)
+    return Pred;
+  
+  const GRState *NotNullState = state->Assume(*LV, true);
+  const GRState *NullState = state->Assume(*LV, false);
+  
+  GRStmtNodeBuilder &Builder = Eng.getBuilder();
+  BugReporter &BR = Eng.getBugReporter();
+  
+    // The explicit NULL case.
+  if (NullState) {
+      // Use the GDM to mark in the state what lval was null.
+    const SVal *PersistentLV = Eng.getBasicVals().getPersistentSVal(*LV);
+    NullState = NullState->set<GRState::NullDerefTag>(PersistentLV);
+    
+    ExplodedNode *N = Builder.generateNode(S, NullState, Pred,
+                                         ProgramPoint::PostNullCheckFailedKind);
+    if (N) {
+      N->markAsSink();
+      
+      if (!NotNullState) { // Explicit null case.
+        if (!BT)
+          BT = new BuiltinBug(NULL, "Null dereference",
+                              "Dereference of null pointer");
+
+        EnhancedBugReport *R =
+          new EnhancedBugReport(*BT, BT->getDescription().c_str(), N);
+        
+        R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+                             bugreporter::GetDerefExpr(N));
+        
+        BR.EmitReport(R);
+        
+        return 0;
+      } else // Implicit null case.
+        ImplicitNullDerefNodes.push_back(N);
+    }
+  }
+  
+  if (!NotNullState)
+    return 0;
+
+  return Builder.generateNode(S, NotNullState, Pred, 
+                              ProgramPoint::PostLocationChecksSucceedKind);
+}
+
+
+void *UndefDerefChecker::getTag() {
+  static int x = 0;
+  return &x;
+}
+
+ExplodedNode *UndefDerefChecker::CheckLocation(const Stmt *S, 
+                                               ExplodedNode *Pred,
+                                               const GRState *state, SVal V,
+                                               GRExprEngine &Eng) {
+  GRStmtNodeBuilder &Builder = Eng.getBuilder();
+  BugReporter &BR = Eng.getBugReporter();
+
+  if (V.isUndef()) {
+    ExplodedNode *N = Builder.generateNode(S, state, Pred, 
+                               ProgramPoint::PostUndefLocationCheckFailedKind);
+    if (N) {
+      N->markAsSink();
+
+      if (!BT)
+        BT = new BuiltinBug(0, "Undefined dereference", 
+                            "Dereference of undefined pointer value");
+
+      EnhancedBugReport *R =
+        new EnhancedBugReport(*BT, BT->getDescription().c_str(), N);
+      R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+                           bugreporter::GetDerefExpr(N));
+      BR.EmitReport(R);
+    }
+    return 0;
+  }
+
+  return Pred;
+}
+
diff --git a/lib/Analysis/DivZeroChecker.cpp b/lib/Analysis/DivZeroChecker.cpp
new file mode 100644
index 0000000..9c2359f
--- /dev/null
+++ b/lib/Analysis/DivZeroChecker.cpp
@@ -0,0 +1,70 @@
+//== DivZeroChecker.cpp - Division by zero checker --------------*- C++ -*--==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines DivZeroChecker, a builtin check in GRExprEngine that performs
+// checks for division by zeros.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h"
+
+using namespace clang;
+
+void *DivZeroChecker::getTag() {
+  static int x;
+  return &x;
+}
+
+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)
+    return;
+
+  if (!B->getRHS()->getType()->isIntegerType() ||
+      !B->getRHS()->getType()->isScalarType())
+    return;
+
+  SVal Denom = C.getState()->getSVal(B->getRHS());
+  const DefinedSVal *DV = dyn_cast<DefinedSVal>(&Denom);
+
+  // Divide-by-undefined handled in the generic checking for uses of
+  // undefined values.
+  if (!DV)
+    return;
+
+  // Check for divide by zero.
+  ConstraintManager &CM = C.getConstraintManager();
+  const GRState *stateNotZero, *stateZero;
+  llvm::tie(stateNotZero, stateZero) = CM.AssumeDual(C.getState(), *DV);
+
+  if (stateZero && !stateNotZero) {
+    if (ExplodedNode *N = C.GenerateNode(B, stateZero, true)) {
+      if (!BT)
+        BT = new BuiltinBug(0, "Division by zero");
+
+      EnhancedBugReport *R = 
+        new EnhancedBugReport(*BT, BT->getDescription().c_str(), N);
+
+      R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+                           bugreporter::GetDenomExpr(N));
+
+      C.EmitReport(R);
+    }
+    return;
+  }
+
+  // If we get here, then the denom should not be zero. We abandon the implicit
+  // zero denom case for now.
+  if (stateNotZero != C.getState())
+    C.addTransition(C.GenerateNode(B, stateNotZero));
+}
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index ea0255d..c71882e 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -25,6 +25,7 @@
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/ADT/ImmutableList.h"
+#include "llvm/ADT/StringSwitch.h"
 
 #ifndef NDEBUG
 #include "llvm/Support/GraphWriter.h"
@@ -117,17 +118,18 @@ void GRExprEngine::CheckerVisit(Stmt *S, ExplodedNodeSet &Dst,
   ExplodedNodeSet Tmp;
   ExplodedNodeSet *PrevSet = &Src;
 
-  for (std::vector<Checker*>::iterator I = Checkers.begin(), E = Checkers.end();
-       I != E; ++I) {
-
-    ExplodedNodeSet *CurrSet = (I+1 == E) ? &Dst
+  for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I)
+  {
+    ExplodedNodeSet *CurrSet = (I+1 == E) ? &Dst 
                                           : (PrevSet == &Tmp) ? &Src : &Tmp;
+
     CurrSet->clear();
-    Checker *checker = *I;
+    void *tag = I->first;
+    Checker *checker = I->second;
 
     for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
          NI != NE; ++NI)
-      checker->GR_Visit(*CurrSet, *Builder, *this, S, *NI, isPrevisit);
+      checker->GR_Visit(*CurrSet, *Builder, *this, S, *NI, tag, isPrevisit);
 
     // Update which NodeSet is the current one.
     PrevSet = CurrSet;
@@ -137,6 +139,41 @@ void GRExprEngine::CheckerVisit(Stmt *S, ExplodedNodeSet &Dst,
   // automatically.
 }
 
+// FIXME: This is largely copy-paste from CheckerVisit().  Need to 
+// unify.
+void GRExprEngine::CheckerVisitBind(Stmt *S, ExplodedNodeSet &Dst,
+                                    ExplodedNodeSet &Src,
+                                    SVal location, SVal val, bool isPrevisit) {
+  
+  if (Checkers.empty()) {
+    Dst = Src;
+    return;
+  }
+  
+  ExplodedNodeSet Tmp;
+  ExplodedNodeSet *PrevSet = &Src;
+  
+  for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I)
+  {
+    ExplodedNodeSet *CurrSet = (I+1 == E) ? &Dst 
+    : (PrevSet == &Tmp) ? &Src : &Tmp;
+    
+    CurrSet->clear();
+    void *tag = I->first;
+    Checker *checker = I->second;
+    
+    for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
+         NI != NE; ++NI)
+      checker->GR_VisitBind(*CurrSet, *Builder, *this, S, *NI, tag, location,
+                            val, isPrevisit);
+    
+    // Update which NodeSet is the current one.
+    PrevSet = CurrSet;
+  }
+  
+  // Don't autotransition.  The CheckerContext objects should do this
+  // automatically.
+}
 //===----------------------------------------------------------------------===//
 // Engine construction and deletion.
 //===----------------------------------------------------------------------===//
@@ -165,9 +202,8 @@ GRExprEngine::GRExprEngine(AnalysisManager &mgr)
 GRExprEngine::~GRExprEngine() {
   BR.FlushReports();
   delete [] NSExceptionInstanceRaiseSelectors;
-  for (std::vector<Checker*>::iterator I=Checkers.begin(), E=Checkers.end();
-       I!=E; ++I)
-    delete *I;
+  for (CheckersOrdered::iterator I=Checkers.begin(), E=Checkers.end(); I!=E;++I)
+    delete I->second;
 }
 
 //===----------------------------------------------------------------------===//
@@ -177,7 +213,7 @@ GRExprEngine::~GRExprEngine() {
 
 void GRExprEngine::setTransferFunctions(GRTransferFuncs* tf) {
   StateMgr.TF = tf;
-  tf->RegisterChecks(getBugReporter());
+  tf->RegisterChecks(*this);
   tf->RegisterPrinters(getStateManager().Printers);
 }
 
@@ -369,11 +405,11 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
 
       if (AMgr.shouldEagerlyAssume() && (B->isRelationalOp() || B->isEqualityOp())) {
         ExplodedNodeSet Tmp;
-        VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp);
+        VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp, false);
         EvalEagerlyAssume(Dst, Tmp, cast<Expr>(S));
       }
       else
-        VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
+        VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst, false);
 
       break;
     }
@@ -395,7 +431,7 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
     }
 
     case Stmt::CompoundAssignOperatorClass:
-      VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
+      VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst, false);
       break;
 
     case Stmt::CompoundLiteralExprClass:
@@ -409,7 +445,6 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
     }
 
     case Stmt::DeclRefExprClass:
-    case Stmt::QualifiedDeclRefExprClass:
       VisitDeclRefExpr(cast<DeclRefExpr>(S), Pred, Dst, false);
       break;
 
@@ -522,7 +557,6 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
       return;
 
     case Stmt::DeclRefExprClass:
-    case Stmt::QualifiedDeclRefExprClass:
       VisitDeclRefExpr(cast<DeclRefExpr>(Ex), Pred, Dst, true);
       return;
 
@@ -565,6 +599,11 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
       return;
     }
 
+    case Stmt::BinaryOperatorClass:
+    case Stmt::CompoundAssignOperatorClass:
+      VisitBinaryOperator(cast<BinaryOperator>(Ex), Pred, Dst, true);
+      return;
+
     default:
       // Arbitrary subexpressions can return aggregate temporaries that
       // can be used in a lvalue context.  We need to enhance our support
@@ -1078,8 +1117,7 @@ void GRExprEngine::VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred,
     SVal L = state->getLValue(Field, state->getSVal(Base));
 
     if (asLValue)
-      MakeNode(Dst, M, *I, state->BindExpr(M, L),
-               ProgramPoint::PostLValueKind);
+      MakeNode(Dst, M, *I, state->BindExpr(M, L), ProgramPoint::PostLValueKind);
     else
       EvalLoad(Dst, M, *I, state, L);
   }
@@ -1087,30 +1125,52 @@ 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, Expr* Ex, ExplodedNode* Pred,
-                            const GRState* state, SVal location, SVal Val) {
+void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, Stmt* Ex, ExplodedNode* Pred,
+                            const GRState* state, SVal location, SVal Val,
+                            bool atDeclInit) {
+  
+  
+  // Do a previsit of the bind.
+  ExplodedNodeSet CheckedSet, Src;
+  Src.Add(Pred);
+  CheckerVisitBind(Ex, CheckedSet, Src, location, Val, true);
+  
+  for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
+       I!=E; ++I) {
+    
+    if (Pred != *I)
+      state = GetState(*I);
+    
+    const GRState* newState = 0;
 
-  const GRState* newState = 0;
+    if (atDeclInit) {
+      const VarRegion *VR =
+        cast<VarRegion>(cast<loc::MemRegionVal>(location).getRegion());
 
-  if (location.isUnknown()) {
-    // We know that the new state will be the same as the old state since
-    // the location of the binding is "unknown".  Consequently, there
-    // is no reason to just create a new node.
-    newState = state;
-  }
-  else {
-    // We are binding to a value other than 'unknown'.  Perform the binding
-    // using the StoreManager.
-    newState = state->bindLoc(cast<Loc>(location), Val);
-  }
+      newState = state->bindDecl(VR, Val);
+    }
+    else {
+      if (location.isUnknown()) {
+        // We know that the new state will be the same as the old state since
+        // the location of the binding is "unknown".  Consequently, there
+        // is no reason to just create a new node.
+        newState = state;
+      }
+      else {
+        // We are binding to a value other than 'unknown'.  Perform the binding
+        // using the StoreManager.
+        newState = state->bindLoc(cast<Loc>(location), Val);
+      }
+    }
 
-  // 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.
-  GRStmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, Pred, newState, Ex,
-                                  newState != state);
+    // 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.
+    GRStmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, *I, newState, Ex,
+                                    newState != state);
 
-  getTF().EvalBind(BuilderRef, location, Val);
+    getTF().EvalBind(BuilderRef, location, Val);
+  }
 }
 
 /// EvalStore - Handle the semantics of a store via an assignment.
@@ -1189,58 +1249,18 @@ ExplodedNode* GRExprEngine::EvalLocation(Stmt* Ex, ExplodedNode* Pred,
   SaveAndRestore<const void*> OldTag(Builder->Tag);
   Builder->Tag = tag;
 
-  // Check for loads/stores from/to undefined values.
-  if (location.isUndef()) {
-    ExplodedNode* N =
-      Builder->generateNode(Ex, state, Pred,
-                            ProgramPoint::PostUndefLocationCheckFailedKind);
-
-    if (N) {
-      N->markAsSink();
-      UndefDeref.insert(N);
-    }
-
-    return 0;
-  }
-
-  // Check for loads/stores from/to unknown locations.  Treat as No-Ops.
-  if (location.isUnknown())
+  if (location.isUnknown() || Checkers.empty())
     return Pred;
 
-  // During a load, one of two possible situations arise:
-  //  (1) A crash, because the location (pointer) was NULL.
-  //  (2) The location (pointer) is not NULL, and the dereference works.
-  //
-  // We add these assumptions.
-
-  Loc LV = cast<Loc>(location);
-
-  // "Assume" that the pointer is not NULL.
-  const GRState *StNotNull = state->Assume(LV, true);
-
-  // "Assume" that the pointer is NULL.
-  const GRState *StNull = state->Assume(LV, false);
-
-  if (StNull) {
-    // Use the Generic Data Map to mark in the state what lval was null.
-    const SVal* PersistentLV = getBasicVals().getPersistentSVal(LV);
-    StNull = StNull->set<GRState::NullDerefTag>(PersistentLV);
-
-    // We don't use "MakeNode" here because the node will be a sink
-    // and we have no intention of processing it later.
-    ExplodedNode* NullNode =
-      Builder->generateNode(Ex, StNull, Pred,
-                            ProgramPoint::PostNullCheckFailedKind);
-
-    if (NullNode) {
-      NullNode->markAsSink();
-      if (StNotNull) ImplicitNullDeref.insert(NullNode);
-      else ExplicitNullDeref.insert(NullNode);
-    }
+  
+  for (CheckersOrdered::iterator I=Checkers.begin(), E=Checkers.end(); I!=E;++I)
+  {
+    Pred = I->second->CheckLocation(Ex, Pred, state, location, *this);
+    if (!Pred)
+      break;
   }
-
-  if (!StNotNull)
-    return NULL;
+  
+  return Pred;
 
   // FIXME: Temporarily disable out-of-bounds checking until we make
   // the logic reflect recent changes to CastRegion and friends.
@@ -1283,10 +1303,6 @@ ExplodedNode* GRExprEngine::EvalLocation(Stmt* Ex, ExplodedNode* Pred,
     }
   }
 #endif
-
-  // Generate a new node indicating the checks succeed.
-  return Builder->generateNode(Ex, StNotNull, Pred,
-                               ProgramPoint::PostLocationChecksSucceedKind);
 }
 
 //===----------------------------------------------------------------------===//
@@ -1445,75 +1461,30 @@ static void MarkNoReturnFunction(const FunctionDecl *FD, CallExpr *CE,
     // HACK: Some functions are not marked noreturn, and don't return.
     //  Here are a few hardwired ones.  If this takes too long, we can
     //  potentially cache these results.
-    const char* s = FD->getIdentifier()->getNameStart();
-
-    switch (FD->getIdentifier()->getLength()) {
-    default:
-      break;
-
-    case 4:
-      if (!memcmp(s, "exit", 4)) Builder->BuildSinks = true;
-      break;
-
-    case 5:
-      if (!memcmp(s, "panic", 5)) Builder->BuildSinks = true;
-      else if (!memcmp(s, "error", 5)) {
-        if (CE->getNumArgs() > 0) {
-          SVal X = state->getSVal(*CE->arg_begin());
-          // FIXME: use Assume to inspect the possible symbolic value of
-          // X. Also check the specific signature of error().
-          nonloc::ConcreteInt* CI = dyn_cast<nonloc::ConcreteInt>(&X);
-          if (CI && CI->getValue() != 0)
-            Builder->BuildSinks = true;
-        }
-      }
-      break;
-
-    case 6:
-      if (!memcmp(s, "Assert", 6)) {
-        Builder->BuildSinks = true;
-        break;
-      }
-
-      // FIXME: This is just a wrapper around throwing an exception.
-      //  Eventually inter-procedural analysis should handle this easily.
-      if (!memcmp(s, "ziperr", 6)) Builder->BuildSinks = true;
-
-      break;
-
-    case 7:
-      if (!memcmp(s, "assfail", 7)) Builder->BuildSinks = true;
-      break;
-
-    case 8:
-      if (!memcmp(s ,"db_error", 8) ||
-          !memcmp(s, "__assert", 8))
-        Builder->BuildSinks = true;
-      break;
-
-    case 12:
-      if (!memcmp(s, "__assert_rtn", 12)) Builder->BuildSinks = true;
-      break;
-
-    case 13:
-      if (!memcmp(s, "__assert_fail", 13)) Builder->BuildSinks = true;
-      break;
-
-    case 14:
-      if (!memcmp(s, "dtrace_assfail", 14) ||
-          !memcmp(s, "yy_fatal_error", 14))
-        Builder->BuildSinks = true;
-      break;
-
-    case 26:
-      if (!memcmp(s, "_XCAssertionFailureHandler", 26) ||
-          !memcmp(s, "_DTAssertionFailureHandler", 26) ||
-          !memcmp(s, "_TSAssertionFailureHandler", 26))
-        Builder->BuildSinks = true;
-
-      break;
-    }
-
+    using llvm::StringRef;
+    bool BuildSinks
+      = llvm::StringSwitch<bool>(StringRef(FD->getIdentifier()->getName()))
+          .Case("exit", true)
+          .Case("panic", true)
+          .Case("error", true)
+          .Case("Assert", true)
+          // FIXME: This is just a wrapper around throwing an exception.
+          //  Eventually inter-procedural analysis should handle this easily.
+          .Case("ziperr", true)
+          .Case("assfail", true)
+          .Case("db_error", true)
+          .Case("__assert", true)
+          .Case("__assert_rtn", true)
+          .Case("__assert_fail", true)
+          .Case("dtrace_assfail", true)
+          .Case("yy_fatal_error", true)
+          .Case("_XCAssertionFailureHandler", true)
+          .Case("_DTAssertionFailureHandler", true)
+          .Case("_TSAssertionFailureHandler", true)
+          .Default(false);
+    
+    if (BuildSinks)
+      Builder->BuildSinks = true;
   }
 }
 
@@ -2042,24 +2013,27 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
     }
   }
 
+  // Handle previsits checks.
+  ExplodedNodeSet Src, DstTmp;
+  Src.Add(Pred);  
+  CheckerVisit(ME, DstTmp, Src, true);
+  
   // Check if we raise an exception.  For now treat these as sinks.  Eventually
   // we will want to handle exceptions properly.
-
   SaveAndRestore<bool> OldSink(Builder->BuildSinks);
-
   if (RaisesException)
     Builder->BuildSinks = true;
 
   // Dispatch to plug-in transfer function.
-
   unsigned size = Dst.size();
   SaveOr OldHasGen(Builder->HasGeneratedNode);
-
-  EvalObjCMessageExpr(Dst, ME, Pred);
+  
+  for (ExplodedNodeSet::iterator DI = DstTmp.begin(), DE = DstTmp.end();
+       DI!=DE; ++DI)
+    EvalObjCMessageExpr(Dst, ME, *DI);
 
   // Handle the case where no nodes where generated.  Auto-generate that
   // contains the updated state if we aren't generating sinks.
-
   if (!Builder->BuildSinks && Dst.size() == size && !Builder->HasGeneratedNode)
     MakeNode(Dst, ME, Pred, state);
 }
@@ -2141,45 +2115,25 @@ void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred,
     Tmp.Add(Pred);
 
   for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
-    const GRState* state = GetState(*I);
-    unsigned Count = Builder->getCurrentBlockCount();
-
-    // Check if 'VD' is a VLA and if so check if has a non-zero size.
-    QualType T = getContext().getCanonicalType(VD->getType());
-    if (VariableArrayType* VLA = dyn_cast<VariableArrayType>(T)) {
-      // FIXME: Handle multi-dimensional VLAs.
-
-      Expr* SE = VLA->getSizeExpr();
-      SVal Size_untested = state->getSVal(SE);
-
-      if (Size_untested.isUndef()) {
-        if (ExplodedNode* N = Builder->generateNode(DS, state, Pred)) {
-          N->markAsSink();
-          ExplicitBadSizedVLA.insert(N);
-        }
-        continue;
-      }
-
-      DefinedOrUnknownSVal Size = cast<DefinedOrUnknownSVal>(Size_untested);
-      const GRState *zeroState =  state->Assume(Size, false);
-      state = state->Assume(Size, true);
+    ExplodedNode *N = *I;
+    const GRState *state;
+
+    for (CheckersOrdered::iterator CI = Checkers.begin(), CE = Checkers.end(); 
+         CI != CE; ++CI) {
+      state = GetState(N);
+      N = CI->second->CheckType(getContext().getCanonicalType(VD->getType()),
+                                N, state, DS, *this);
+      if (!N)
+        break;
+    }
 
-      if (zeroState) {
-        if (ExplodedNode* N = Builder->generateNode(DS, zeroState, Pred)) {
-          N->markAsSink();
-          if (state)
-            ImplicitBadSizedVLA.insert(N);
-          else
-            ExplicitBadSizedVLA.insert(N);
-        }
-      }
+    if (!N)
+      continue;
 
-      if (!state)
-        continue;
-    }
+    state = GetState(N);
 
     // Decls without InitExpr are not initialized explicitly.
-    const LocationContext *LC = (*I)->getLocationContext();
+    const LocationContext *LC = N->getLocationContext();
 
     if (InitEx) {
       SVal InitVal = state->getSVal(InitEx);
@@ -2189,20 +2143,15 @@ void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred,
       // UnknownVal.
       if (InitVal.isUnknown() ||
           !getConstraintManager().canReasonAbout(InitVal)) {
-        InitVal = ValMgr.getConjuredSymbolVal(NULL, InitEx, Count);
+        InitVal = ValMgr.getConjuredSymbolVal(NULL, InitEx, 
+                                               Builder->getCurrentBlockCount());
       }
-
-      state = state->bindDecl(VD, LC, InitVal);
-
-      // 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.
-      GRStmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, *I, state, DS,true);
-      getTF().EvalBind(BuilderRef, loc::MemRegionVal(state->getRegion(VD, LC)),
-                       InitVal);
+      
+      EvalBind(Dst, DS, *I, state, loc::MemRegionVal(state->getRegion(VD, LC)),
+               InitVal, true);                                                     
     }
     else {
-      state = state->bindDeclWithNoInit(VD, LC);
+      state = state->bindDeclWithNoInit(state->getRegion(VD, LC));
       MakeNode(Dst, DS, *I, state);
     }
   }
@@ -2752,7 +2701,7 @@ void GRExprEngine::VisitReturnStmt(ReturnStmt* S, ExplodedNode* Pred,
 
 void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
                                        ExplodedNode* Pred,
-                                       ExplodedNodeSet& Dst) {
+                                       ExplodedNodeSet& Dst, bool asLValue) {
 
   ExplodedNodeSet Tmp1;
   Expr* LHS = B->getLHS()->IgnoreParens();
@@ -2798,10 +2747,12 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
           unsigned Count = Builder->getCurrentBlockCount();
           RightV = ValMgr.getConjuredSymbolVal(NULL, B->getRHS(), Count);
         }
-        
+
+        SVal ExprVal = asLValue ? LeftV : RightV;
+
         // Simulate the effects of a "store":  bind the value of the RHS
         // to the L-Value represented by the LHS.
-        EvalStore(Dst, B, LHS, *I2, state->BindExpr(B, RightV), LeftV, RightV);
+        EvalStore(Dst, B, LHS, *I2, state->BindExpr(B, ExprVal), LeftV, RightV);
         continue;
       }
       
@@ -2930,6 +2881,15 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
 }
 
 //===----------------------------------------------------------------------===//
+// Checker registration/lookup.
+//===----------------------------------------------------------------------===//
+
+Checker *GRExprEngine::lookupChecker(void *tag) const {
+  CheckerMap::iterator I = CheckerM.find(tag);
+  return (I == CheckerM.end()) ? NULL : Checkers[I->second].second;
+}
+
+//===----------------------------------------------------------------------===//
 // Visualization.
 //===----------------------------------------------------------------------===//
 
@@ -2941,7 +2901,8 @@ namespace llvm {
 template<>
 struct VISIBILITY_HIDDEN DOTGraphTraits<ExplodedNode*> :
   public DefaultDOTGraphTraits {
-
+  // FIXME: Since we do not cache error nodes in GRExprEngine now, this does not
+  // work.
   static std::string getNodeAttributes(const ExplodedNode* N, void*) {
 
     if (GraphPrintCheckerState->isImplicitNullDeref(N) ||
diff --git a/lib/Analysis/GRExprEngineInternalChecks.cpp b/lib/Analysis/GRExprEngineInternalChecks.cpp
index da24192..695f0b0 100644
--- a/lib/Analysis/GRExprEngineInternalChecks.cpp
+++ b/lib/Analysis/GRExprEngineInternalChecks.cpp
@@ -15,6 +15,13 @@
 #include "clang/Analysis/PathSensitive/BugReporter.h"
 #include "clang/Analysis/PathSensitive/GRExprEngine.h"
 #include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+#include "clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h"
+#include "clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h"
+#include "clang/Analysis/PathSensitive/Checkers/BadCallChecker.h"
+#include "clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h"
+#include "clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h"
+#include "clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h"
+#include "clang/Analysis/PathSensitive/Checkers/VLASizeChecker.h"
 #include "clang/Analysis/PathDiagnostic.h"
 #include "clang/Basic/SourceManager.h"
 #include "llvm/Support/Compiler.h"
@@ -40,10 +47,8 @@ ExplodedNode* GetNode(GRExprEngine::undef_arg_iterator I) {
 //===----------------------------------------------------------------------===//
 // Bug Descriptions.
 //===----------------------------------------------------------------------===//
-
-namespace {
-
-class VISIBILITY_HIDDEN BuiltinBugReport : public RangedBugReport {
+namespace clang {
+class BuiltinBugReport : public RangedBugReport {
 public:
   BuiltinBugReport(BugType& bt, const char* desc,
                    ExplodedNode *n)
@@ -57,30 +62,10 @@ public:
                                const ExplodedNode* N);
 };
 
-class VISIBILITY_HIDDEN BuiltinBug : public BugType {
-  GRExprEngine &Eng;
-protected:
-  const std::string desc;
-public:
-  BuiltinBug(GRExprEngine *eng, const char* n, const char* d)
-    : BugType(n, "Logic errors"), Eng(*eng), desc(d) {}
-
-  BuiltinBug(GRExprEngine *eng, const char* n)
-    : BugType(n, "Logic errors"), Eng(*eng), desc(n) {}
-
-  const std::string &getDescription() const { return desc; }
-
-  virtual void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {}
-
-  void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, Eng); }
-
-  virtual void registerInitialVisitors(BugReporterContext& BRC,
-                                       const ExplodedNode* N,
-                                       BuiltinBugReport *R) {}
-
-  template <typename ITER> void Emit(BugReporter& BR, ITER I, ITER E);
-};
-
+void BuiltinBugReport::registerInitialVisitors(BugReporterContext& BRC,
+                                               const ExplodedNode* N) {
+  static_cast<BuiltinBug&>(getBugType()).registerInitialVisitors(BRC, N, this);
+}
 
 template <typename ITER>
 void BuiltinBug::Emit(BugReporter& BR, ITER I, ITER E) {
@@ -88,27 +73,6 @@ void BuiltinBug::Emit(BugReporter& BR, ITER I, ITER E) {
                                                          GetNode(I)));
 }
 
-void BuiltinBugReport::registerInitialVisitors(BugReporterContext& BRC,
-                                               const ExplodedNode* N) {
-  static_cast<BuiltinBug&>(getBugType()).registerInitialVisitors(BRC, N, this);
-}
-
-class VISIBILITY_HIDDEN NullDeref : public BuiltinBug {
-public:
-  NullDeref(GRExprEngine* eng)
-    : BuiltinBug(eng,"Null dereference", "Dereference of null pointer") {}
-
-  void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
-    Emit(BR, Eng.null_derefs_begin(), Eng.null_derefs_end());
-  }
-
-  void registerInitialVisitors(BugReporterContext& BRC,
-                               const ExplodedNode* N,
-                               BuiltinBugReport *R) {
-    registerTrackNullOrUndefValue(BRC, GetDerefExpr(N), N);
-  }
-};
-
 class VISIBILITY_HIDDEN NilReceiverStructRet : public BuiltinBug {
 public:
   NilReceiverStructRet(GRExprEngine* eng) :
@@ -175,34 +139,6 @@ public:
   }
 };
 
-class VISIBILITY_HIDDEN UndefinedDeref : public BuiltinBug {
-public:
-  UndefinedDeref(GRExprEngine* eng)
-    : BuiltinBug(eng,"Dereference of undefined pointer value") {}
-
-  void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
-    Emit(BR, Eng.undef_derefs_begin(), Eng.undef_derefs_end());
-  }
-
-  void registerInitialVisitors(BugReporterContext& BRC,
-                               const ExplodedNode* N,
-                               BuiltinBugReport *R) {
-    registerTrackNullOrUndefValue(BRC, GetDerefExpr(N), N);
-  }
-};
-
-class VISIBILITY_HIDDEN DivZero : public BuiltinBug {
-public:
-  DivZero(GRExprEngine* eng = 0)
-    : BuiltinBug(eng,"Division by zero") {}
-
-  void registerInitialVisitors(BugReporterContext& BRC,
-                               const ExplodedNode* N,
-                               BuiltinBugReport *R) {
-    registerTrackNullOrUndefValue(BRC, GetDenomExpr(N), N);
-  }
-};
-
 class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
 public:
   UndefResult(GRExprEngine* eng)
@@ -279,20 +215,6 @@ public:
   }
 };
 
-class VISIBILITY_HIDDEN BadCall : public BuiltinBug {
-public:
-  BadCall(GRExprEngine *eng = 0)
-  : BuiltinBug(eng, "Invalid function call",
-        "Called function pointer is a null or undefined pointer value") {}
-
-  void registerInitialVisitors(BugReporterContext& BRC,
-                               const ExplodedNode* N,
-                               BuiltinBugReport *R) {
-    registerTrackNullOrUndefValue(BRC, GetCalleeExpr(N), N);
-  }
-};
-
-
 class VISIBILITY_HIDDEN ArgReport : public BuiltinBugReport {
   const Stmt *Arg;
 public:
@@ -528,276 +450,8 @@ public:
   }
 };
 
-class VISIBILITY_HIDDEN BadSizeVLA : public BuiltinBug {
-public:
-  BadSizeVLA(GRExprEngine* eng) :
-    BuiltinBug(eng, "Bad variable-length array (VLA) size") {}
-
-  void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
-    for (GRExprEngine::ErrorNodes::iterator
-          I = Eng.ExplicitBadSizedVLA.begin(),
-          E = Eng.ExplicitBadSizedVLA.end(); I!=E; ++I) {
-
-      // Determine whether this was a 'zero-sized' VLA or a VLA with an
-      // undefined size.
-      ExplodedNode* N = *I;
-      PostStmt PS = cast<PostStmt>(N->getLocation());
-      const DeclStmt *DS = cast<DeclStmt>(PS.getStmt());
-      VarDecl* VD = cast<VarDecl>(*DS->decl_begin());
-      QualType T = Eng.getContext().getCanonicalType(VD->getType());
-      VariableArrayType* VT = cast<VariableArrayType>(T);
-      Expr* SizeExpr = VT->getSizeExpr();
-
-      std::string buf;
-      llvm::raw_string_ostream os(buf);
-      os << "The expression used to specify the number of elements in the "
-            "variable-length array (VLA) '"
-         << VD->getNameAsString() << "' evaluates to ";
-
-      bool isUndefined = N->getState()->getSVal(SizeExpr).isUndef();
-
-      if (isUndefined)
-        os << "an undefined or garbage value.";
-      else
-        os << "0. VLAs with no elements have undefined behavior.";
-
-      std::string shortBuf;
-      llvm::raw_string_ostream os_short(shortBuf);
-      os_short << "Variable-length array '" << VD->getNameAsString() << "' "
-               << (isUndefined ? "garbage value for array size"
-                   : "has zero elements (undefined behavior)");
-
-      ArgReport *report = new ArgReport(*this, os_short.str().c_str(),
-                                        os.str().c_str(), N, SizeExpr);
-
-      report->addRange(SizeExpr->getSourceRange());
-      BR.EmitReport(report);
-    }
-  }
-
-  void registerInitialVisitors(BugReporterContext& BRC,
-                               const ExplodedNode* N,
-                               BuiltinBugReport *R) {
-    registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
-                                  N);
-  }
-};
-
-//===----------------------------------------------------------------------===//
-// __attribute__(nonnull) checking
-
-class VISIBILITY_HIDDEN CheckAttrNonNull :
-    public CheckerVisitor<CheckAttrNonNull> {
-
-  BugType *BT;
-
-public:
-  CheckAttrNonNull() : BT(0) {}
-  ~CheckAttrNonNull() {}
-
-  const void *getTag() {
-    static int x = 0;
-    return &x;
-  }
-
-  void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
-    const GRState *state = C.getState();
-    const GRState *originalState = state;
-
-    // Check if the callee has a 'nonnull' attribute.
-    SVal X = state->getSVal(CE->getCallee());
-
-    const FunctionDecl* FD = X.getAsFunctionDecl();
-    if (!FD)
-      return;
+} // end clang namespace
 
-    const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
-    if (!Att)
-      return;
-
-    // Iterate through the arguments of CE and check them for null.
-    unsigned idx = 0;
-
-    for (CallExpr::const_arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
-         ++I, ++idx) {
-
-      if (!Att->isNonNull(idx))
-        continue;
-
-      const SVal &V = state->getSVal(*I);
-      const DefinedSVal *DV = dyn_cast<DefinedSVal>(&V);
-
-      if (!DV)
-        continue;
-
-      ConstraintManager &CM = C.getConstraintManager();
-      const GRState *stateNotNull, *stateNull;
-      llvm::tie(stateNotNull, stateNull) = CM.AssumeDual(state, *DV);
-
-      if (stateNull && !stateNotNull) {
-        // Generate an error node.  Check for a null node in case
-        // we cache out.
-        if (ExplodedNode *errorNode = C.GenerateNode(CE, stateNull, true)) {
-
-          // Lazily allocate the BugType object if it hasn't already been
-          // created. Ownership is transferred to the BugReporter object once
-          // the BugReport is passed to 'EmitWarning'.
-          if (!BT)
-            BT = new BugType("Argument with 'nonnull' attribute passed null",
-                             "API");
-
-          EnhancedBugReport *R =
-            new EnhancedBugReport(*BT,
-                                  "Null pointer passed as an argument to a "
-                                  "'nonnull' parameter", errorNode);
-
-          // Highlight the range of the argument that was null.
-          const Expr *arg = *I;
-          R->addRange(arg->getSourceRange());
-          R->addVisitorCreator(registerTrackNullOrUndefValue, arg);
-
-          // Emit the bug report.
-          C.EmitReport(R);
-        }
-
-        // Always return.  Either we cached out or we just emitted an error.
-        return;
-      }
-
-      // If a pointer value passed the check we should assume that it is
-      // indeed not null from this point forward.
-      assert(stateNotNull);
-      state = stateNotNull;
-    }
-
-    // If we reach here all of the arguments passed the nonnull check.
-    // If 'state' has been updated generated a new node.
-    if (state != originalState)
-      C.addTransition(C.GenerateNode(CE, state));
-  }
-};
-} // end anonymous namespace
-
-// Undefined arguments checking.
-namespace {
-class VISIBILITY_HIDDEN CheckUndefinedArg
-  : public CheckerVisitor<CheckUndefinedArg> {
-
-  BadArg *BT;
-
-public:
-  CheckUndefinedArg() : BT(0) {}
-  ~CheckUndefinedArg() {}
-
-  const void *getTag() {
-    static int x = 0;
-    return &x;
-  }
-
-  void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
-};
-
-void CheckUndefinedArg::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE){
-  for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end();
-       I != E; ++I) {
-    if (C.getState()->getSVal(*I).isUndef()) {
-      if (ExplodedNode *ErrorNode = C.GenerateNode(CE, true)) {
-        if (!BT)
-          BT = new BadArg();
-        // Generate a report for this bug.
-        ArgReport *Report = new ArgReport(*BT, BT->getDescription().c_str(),
-                                          ErrorNode, *I);
-        Report->addRange((*I)->getSourceRange());
-        C.EmitReport(Report);
-      }
-    }
-  }
-}
-
-class VISIBILITY_HIDDEN CheckBadCall : public CheckerVisitor<CheckBadCall> {
-  BadCall *BT;
-
-public:
-  CheckBadCall() : BT(0) {}
-  ~CheckBadCall() {}
-
-  const void *getTag() {
-    static int x = 0;
-    return &x;
-  }
-
-  void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
-};
-
-void CheckBadCall::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
-  const Expr *Callee = CE->getCallee()->IgnoreParens();
-  SVal L = C.getState()->getSVal(Callee);
-
-  if (L.isUndef() || isa<loc::ConcreteInt>(L)) {
-    if (ExplodedNode *N = C.GenerateNode(CE, true)) {
-      if (!BT)
-        BT = new BadCall();
-      C.EmitReport(new BuiltinBugReport(*BT, BT->getDescription().c_str(), N));
-    }
-  }
-}
-
-class VISIBILITY_HIDDEN CheckDivZero : public CheckerVisitor<CheckDivZero> {
-  DivZero *BT;
-public:
-  CheckDivZero() : BT(0) {}
-  ~CheckDivZero() {}
-
-  const void *getTag() {
-    static int x;
-    return &x;
-  }
-
-  void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
-};
-
-void CheckDivZero::PreVisitBinaryOperator(CheckerContext &C,
-                                          const BinaryOperator *B) {
-  BinaryOperator::Opcode Op = B->getOpcode();
-  if (Op != BinaryOperator::Div &&
-      Op != BinaryOperator::Rem &&
-      Op != BinaryOperator::DivAssign &&
-      Op != BinaryOperator::RemAssign)
-    return;
-
-  if (!B->getRHS()->getType()->isIntegerType() ||
-      !B->getRHS()->getType()->isScalarType())
-    return;
-
-  SVal Denom = C.getState()->getSVal(B->getRHS());
-  const DefinedSVal *DV = dyn_cast<DefinedSVal>(&Denom);
-
-  // Divide-by-undefined handled in the generic checking for uses of
-  // undefined values.
-  if (!DV)
-    return;
-
-  // Check for divide by zero.
-  ConstraintManager &CM = C.getConstraintManager();
-  const GRState *stateNotZero, *stateZero;
-  llvm::tie(stateNotZero, stateZero) = CM.AssumeDual(C.getState(), *DV);
-
-  if (stateZero && !stateNotZero) {
-    if (ExplodedNode *N = C.GenerateNode(B, stateZero, true)) {
-      if (!BT)
-        BT = new DivZero();
-
-      C.EmitReport(new BuiltinBugReport(*BT, BT->getDescription().c_str(), N));
-    }
-    return;
-  }
-
-  // If we get here, then the denom should not be zero. We abandon the implicit
-  // zero denom case for now.
-  if (stateNotZero != C.getState())
-    C.addTransition(C.GenerateNode(B, stateNotZero));
-}
-}
 //===----------------------------------------------------------------------===//
 // Check registration.
 //===----------------------------------------------------------------------===//
@@ -808,8 +462,6 @@ void GRExprEngine::RegisterInternalChecks() {
   // create BugReports on-the-fly but instead wait until GRExprEngine finishes
   // analyzing a function.  Generation of BugReport objects is done via a call
   // to 'FlushReports' from BugReporter.
-  BR.Register(new NullDeref(this));
-  BR.Register(new UndefinedDeref(this));
   BR.Register(new UndefBranch(this));
   BR.Register(new UndefResult(this));
   BR.Register(new RetStack(this));
@@ -817,7 +469,6 @@ void GRExprEngine::RegisterInternalChecks() {
   BR.Register(new BadMsgExprArg(this));
   BR.Register(new BadReceiver(this));
   BR.Register(new OutOfBoundMemoryAccess(this));
-  BR.Register(new BadSizeVLA(this));
   BR.Register(new NilReceiverStructRet(this));
   BR.Register(new NilReceiverLargerThanVoidPtrRet(this));
 
@@ -826,8 +477,13 @@ void GRExprEngine::RegisterInternalChecks() {
   // their associated BugType will get registered with the BugReporter
   // automatically.  Note that the check itself is owned by the GRExprEngine
   // object.
-  registerCheck(new CheckAttrNonNull());
-  registerCheck(new CheckUndefinedArg());
-  registerCheck(new CheckBadCall());
-  registerCheck(new CheckDivZero());
+  registerCheck(new AttrNonNullChecker());
+  registerCheck(new UndefinedArgChecker());
+  registerCheck(new UndefinedAssignmentChecker());
+  registerCheck(new BadCallChecker());
+  registerCheck(new DivZeroChecker());
+  registerCheck(new UndefDerefChecker());
+  registerCheck(new NullDerefChecker());
+  registerCheck(new UndefSizedVLAChecker());
+  registerCheck(new ZeroSizedVLAChecker());
 }
diff --git a/lib/Analysis/NSAutoreleasePoolChecker.cpp b/lib/Analysis/NSAutoreleasePoolChecker.cpp
new file mode 100644
index 0000000..e0a8d0d
--- /dev/null
+++ b/lib/Analysis/NSAutoreleasePoolChecker.cpp
@@ -0,0 +1,84 @@
+//=- NSAutoreleasePoolChecker.cpp --------------------------------*- 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 a NSAutoreleasePoolChecker, a small checker that warns
+//  about subpar uses of NSAutoreleasePool.  Note that while the check itself
+//  (in it's current form) could be written as a flow-insensitive check, in
+//  can be potentially enhanced in the future with flow-sensitive information.
+//  It is also a good example of the CheckerVisitor interface. 
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+#include "BasicObjCFoundationChecks.h"
+#include "llvm/Support/Compiler.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Decl.h"
+
+using namespace clang;
+
+namespace {
+class VISIBILITY_HIDDEN NSAutoreleasePoolChecker
+  : public CheckerVisitor<NSAutoreleasePoolChecker> {
+      
+  Selector releaseS;
+
+public:
+    NSAutoreleasePoolChecker(Selector release_s) : releaseS(release_s) {}
+    
+  static void *getTag() {
+    static int x = 0;
+    return &x;
+  }
+
+  void PreVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *ME);    
+};
+
+} // end anonymous namespace
+
+
+void clang::RegisterNSAutoreleasePoolChecks(GRExprEngine &Eng) {
+  ASTContext &Ctx = Eng.getContext();
+  if (Ctx.getLangOptions().getGCMode() != LangOptions::NonGC) {    
+    Eng.registerCheck(new NSAutoreleasePoolChecker(GetNullarySelector("release",
+                                                                      Ctx)));
+  }
+}
+
+void
+NSAutoreleasePoolChecker::PreVisitObjCMessageExpr(CheckerContext &C,
+                                                  const ObjCMessageExpr *ME) {
+  
+  const Expr *receiver = ME->getReceiver();
+  if (!receiver)
+    return;
+  
+  // FIXME: Enhance with value-tracking information instead of consulting
+  // the type of the expression.
+  const ObjCObjectPointerType* PT =
+    receiver->getType()->getAs<ObjCObjectPointerType>();
+  const ObjCInterfaceDecl* OD = PT->getInterfaceDecl();
+  if (!OD)
+    return;  
+  if (!OD->getIdentifier()->getName().equals("NSAutoreleasePool"))
+    return;
+  
+  // Sending 'release' message?
+  if (ME->getSelector() != releaseS)
+    return;
+                     
+  SourceRange R = ME->getSourceRange();
+
+  C.getBugReporter().EmitBasicReport("Use -drain instead of -release",
+    "API Upgrade (Apple)",
+    "Use -drain instead of -release when using NSAutoreleasePool "
+    "and garbage collection", ME->getLocStart(), &R, 1);
+}
diff --git a/lib/Analysis/NSErrorChecker.cpp b/lib/Analysis/NSErrorChecker.cpp
new file mode 100644
index 0000000..307686f
--- /dev/null
+++ b/lib/Analysis/NSErrorChecker.cpp
@@ -0,0 +1,241 @@
+//=- NSErrorCheckerer.cpp - Coding conventions for uses of NSError -*- 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 a CheckNSError, a flow-insenstive check
+//  that determines if an Objective-C class interface correctly returns
+//  a non-void return type.
+//
+//  File under feature request PR 2600.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/LocalCheckers.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+#include "clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h"
+#include "BasicObjCFoundationChecks.h"
+#include "llvm/Support/Compiler.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Decl.h"
+#include "llvm/ADT/SmallVector.h"
+
+using namespace clang;
+
+namespace {
+class VISIBILITY_HIDDEN NSErrorChecker : public BugType {
+  const Decl &CodeDecl;
+  const bool isNSErrorWarning;
+  IdentifierInfo * const II;
+  GRExprEngine &Eng;
+
+  void CheckSignature(const ObjCMethodDecl& MD, QualType& ResultTy,
+                      llvm::SmallVectorImpl<VarDecl*>& ErrorParams);
+
+  void CheckSignature(const FunctionDecl& MD, QualType& ResultTy,
+                      llvm::SmallVectorImpl<VarDecl*>& ErrorParams);
+
+  bool CheckNSErrorArgument(QualType ArgTy);
+  bool CheckCFErrorArgument(QualType ArgTy);
+
+  void CheckParamDeref(const VarDecl *V, const LocationContext *LC,
+                       const GRState *state, BugReporter& BR);
+
+  void EmitRetTyWarning(BugReporter& BR, const Decl& CodeDecl);
+
+public:
+  NSErrorChecker(const Decl &D, bool isNSError, GRExprEngine& eng)
+    : BugType(isNSError ? "NSError** null dereference"
+                        : "CFErrorRef* null dereference",
+              "Coding conventions (Apple)"),
+    CodeDecl(D),
+    isNSErrorWarning(isNSError),
+    II(&eng.getContext().Idents.get(isNSErrorWarning ? "NSError":"CFErrorRef")),
+    Eng(eng) {}
+
+  void FlushReports(BugReporter& BR);
+};
+
+} // end anonymous namespace
+
+void clang::RegisterNSErrorChecks(BugReporter& BR, GRExprEngine &Eng,
+                                  const Decl &D) {
+  BR.Register(new NSErrorChecker(D, true, Eng));
+  BR.Register(new NSErrorChecker(D, false, Eng));
+}
+
+void NSErrorChecker::FlushReports(BugReporter& BR) {
+  // Get the analysis engine and the exploded analysis graph.
+  ExplodedGraph& G = Eng.getGraph();
+
+  // Get the ASTContext, which is useful for querying type information.
+  ASTContext &Ctx = BR.getContext();
+
+  QualType ResultTy;
+  llvm::SmallVector<VarDecl*, 5> ErrorParams;
+
+  if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(&CodeDecl))
+    CheckSignature(*MD, ResultTy, ErrorParams);
+  else if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(&CodeDecl))
+    CheckSignature(*FD, ResultTy, ErrorParams);
+  else
+    return;
+
+  if (ErrorParams.empty())
+    return;
+
+  if (ResultTy == Ctx.VoidTy) EmitRetTyWarning(BR, CodeDecl);
+
+  for (ExplodedGraph::roots_iterator RI=G.roots_begin(), RE=G.roots_end();
+       RI!=RE; ++RI) {
+    // Scan the parameters for an implicit null dereference.
+    for (llvm::SmallVectorImpl<VarDecl*>::iterator I=ErrorParams.begin(),
+          E=ErrorParams.end(); I!=E; ++I)
+        CheckParamDeref(*I, (*RI)->getLocationContext(), (*RI)->getState(), BR);
+  }
+}
+
+void NSErrorChecker::EmitRetTyWarning(BugReporter& BR, const Decl& CodeDecl) {
+  std::string sbuf;
+  llvm::raw_string_ostream os(sbuf);
+
+  if (isa<ObjCMethodDecl>(CodeDecl))
+    os << "Method";
+  else
+    os << "Function";
+
+  os << " accepting ";
+  os << (isNSErrorWarning ? "NSError**" : "CFErrorRef*");
+  os << " should have a non-void return value to indicate whether or not an "
+        "error occurred";
+
+  BR.EmitBasicReport(isNSErrorWarning
+                     ? "Bad return type when passing NSError**"
+                     : "Bad return type when passing CFError*",
+                     getCategory().c_str(), os.str().c_str(),
+                     CodeDecl.getLocation());
+}
+
+void
+NSErrorChecker::CheckSignature(const ObjCMethodDecl& M, QualType& ResultTy,
+                             llvm::SmallVectorImpl<VarDecl*>& ErrorParams) {
+
+  ResultTy = M.getResultType();
+
+  for (ObjCMethodDecl::param_iterator I=M.param_begin(),
+       E=M.param_end(); I!=E; ++I)  {
+
+    QualType T = (*I)->getType();
+
+    if (isNSErrorWarning) {
+      if (CheckNSErrorArgument(T)) ErrorParams.push_back(*I);
+    }
+    else if (CheckCFErrorArgument(T))
+      ErrorParams.push_back(*I);
+  }
+}
+
+void
+NSErrorChecker::CheckSignature(const FunctionDecl& F, QualType& ResultTy,
+                             llvm::SmallVectorImpl<VarDecl*>& ErrorParams) {
+
+  ResultTy = F.getResultType();
+
+  for (FunctionDecl::param_const_iterator I = F.param_begin(),
+                                          E = F.param_end(); I != E; ++I)  {
+
+    QualType T = (*I)->getType();
+
+    if (isNSErrorWarning) {
+      if (CheckNSErrorArgument(T)) ErrorParams.push_back(*I);
+    }
+    else if (CheckCFErrorArgument(T))
+      ErrorParams.push_back(*I);
+  }
+}
+
+
+bool NSErrorChecker::CheckNSErrorArgument(QualType ArgTy) {
+
+  const PointerType* PPT = ArgTy->getAs<PointerType>();
+  if (!PPT)
+    return false;
+
+  const ObjCObjectPointerType* PT =
+    PPT->getPointeeType()->getAs<ObjCObjectPointerType>();
+
+  if (!PT)
+    return false;
+
+  const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
+
+  // FIXME: Can ID ever be NULL?
+  if (ID)
+    return II == ID->getIdentifier();
+
+  return false;
+}
+
+bool NSErrorChecker::CheckCFErrorArgument(QualType ArgTy) {
+
+  const PointerType* PPT = ArgTy->getAs<PointerType>();
+  if (!PPT) return false;
+
+  const TypedefType* TT = PPT->getPointeeType()->getAs<TypedefType>();
+  if (!TT) return false;
+
+  return TT->getDecl()->getIdentifier() == II;
+}
+
+void NSErrorChecker::CheckParamDeref(const VarDecl *Param,
+                                   const LocationContext *LC,
+                                   const GRState *rootState,
+                                   BugReporter& BR) {
+
+  SVal ParamL = rootState->getLValue(Param, LC);
+  const MemRegion* ParamR = cast<loc::MemRegionVal>(ParamL).getRegionAs<VarRegion>();
+  assert (ParamR && "Parameters always have VarRegions.");
+  SVal ParamSVal = rootState->getSVal(ParamR);
+
+  // FIXME: For now assume that ParamSVal is symbolic.  We need to generalize
+  // this later.
+  SymbolRef ParamSym = ParamSVal.getAsLocSymbol();
+  if (!ParamSym)
+    return;
+
+  // Iterate over the implicit-null dereferences.
+  NullDerefChecker *Checker = Eng.getChecker<NullDerefChecker>();
+  assert(Checker && "NullDerefChecker not exist.");
+  for (NullDerefChecker::iterator I = Checker->implicit_nodes_begin(),
+         E = Checker->implicit_nodes_end(); I != E; ++I) {
+
+    const GRState *state = (*I)->getState();
+    const SVal* X = state->get<GRState::NullDerefTag>();
+
+    if (!X || X->getAsSymbol() != ParamSym)
+      continue;
+
+    // Emit an error.
+    std::string sbuf;
+    llvm::raw_string_ostream os(sbuf);
+      os << "Potential null dereference.  According to coding standards ";
+
+    if (isNSErrorWarning)
+      os << "in 'Creating and Returning NSError Objects' the parameter '";
+    else
+      os << "documented in CoreFoundation/CFError.h the parameter '";
+
+    os << Param->getNameAsString() << "' may be null.";
+
+    BugReport *report = new BugReport(*this, os.str().c_str(), *I);
+    // FIXME: Notable symbols are now part of the report.  We should
+    //  add support for notable symbols in BugReport.
+    //    BR.addNotableSymbol(SV->getSymbol());
+    BR.EmitReport(report);
+  }
+}
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index 780772a..dbf8c42 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -275,11 +275,11 @@ public:
   const GRState *BindCompoundLiteral(const GRState *state,
                                      const CompoundLiteralExpr* CL, SVal V);
 
-  const GRState *BindDecl(const GRState *ST, const VarDecl *VD,
-                          const LocationContext *LC, SVal InitVal);
+  const GRState *BindDecl(const GRState *ST, const VarRegion *VR,
+                          SVal InitVal);
 
-  const GRState *BindDeclWithNoInit(const GRState *state, const VarDecl*,
-                                    const LocationContext *) {
+  const GRState *BindDeclWithNoInit(const GRState *state, 
+                                    const VarRegion *) {
     return state;
   }
 
@@ -1409,12 +1409,10 @@ const GRState *RegionStoreManager::Bind(const GRState *state, Loc L, SVal V) {
 }
 
 const GRState *RegionStoreManager::BindDecl(const GRState *ST,
-                                            const VarDecl *VD,
-                                            const LocationContext *LC,
+                                            const VarRegion *VR, 
                                             SVal InitVal) {
 
-  QualType T = VD->getType();
-  VarRegion* VR = MRMgr.getVarRegion(VD, LC);
+  QualType T = VR->getDecl()->getType();
 
   if (T->isArrayType())
     return BindArray(ST, VR, InitVal);
@@ -1630,6 +1628,8 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
   // Process the "intermediate" roots to find if they are referenced by
   // real roots.
   llvm::SmallVector<RBDNode, 10> WorkList;
+  llvm::SmallVector<RBDNode, 10> Postponed;
+
   llvm::DenseSet<const MemRegion*> IntermediateVisited;
   
   while (!IntermediateRoots.empty()) {
@@ -1647,8 +1647,11 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
     }
     
     if (const SymbolicRegion* SR = dyn_cast<SymbolicRegion>(R)) {
-      if (SymReaper.isLive(SR->getSymbol()))
-        WorkList.push_back(std::make_pair(&state, SR));
+      llvm::SmallVectorImpl<RBDNode> &Q =      
+        SymReaper.isLive(SR->getSymbol()) ? WorkList : Postponed;
+      
+        Q.push_back(std::make_pair(&state, SR));
+
       continue;
     }
     
@@ -1667,6 +1670,7 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
   
   llvm::DenseSet<RBDNode> Visited;
   
+tryAgain:
   while (!WorkList.empty()) {
     RBDNode N = WorkList.back();
     WorkList.pop_back();
@@ -1740,6 +1744,21 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
     }
   }
   
+  // See if any postponed SymbolicRegions are actually live now, after
+  // having done a scan.
+  for (llvm::SmallVectorImpl<RBDNode>::iterator I = Postponed.begin(),
+       E = Postponed.end() ; I != E ; ++I) {    
+    if (const SymbolicRegion *SR = cast_or_null<SymbolicRegion>(I->second)) {
+      if (SymReaper.isLive(SR->getSymbol())) {
+        WorkList.push_back(*I);
+        I->second = NULL;
+      }
+    }
+  }
+  
+  if (!WorkList.empty())
+    goto tryAgain;
+  
   // We have now scanned the store, marking reachable regions and symbols
   // as live.  We now remove all the regions that are dead from the store
   // as well as update DSymbols with the set symbols that are now dead.
diff --git a/lib/Analysis/UndefinedArgChecker.cpp b/lib/Analysis/UndefinedArgChecker.cpp
new file mode 100644
index 0000000..a229f55
--- /dev/null
+++ b/lib/Analysis/UndefinedArgChecker.cpp
@@ -0,0 +1,43 @@
+//===--- UndefinedArgChecker.h - Undefined arguments checker ----*- C++ -*--==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines BadCallChecker, a builtin check in GRExprEngine that performs
+// checks for undefined arguments.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+
+using namespace clang;
+
+void *UndefinedArgChecker::getTag() {
+  static int x = 0;
+  return &x;
+}
+
+void UndefinedArgChecker::PreVisitCallExpr(CheckerContext &C, 
+                                           const CallExpr *CE){
+  for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end();
+       I != E; ++I) {
+    if (C.getState()->getSVal(*I).isUndef()) {
+      if (ExplodedNode *N = C.GenerateNode(CE, true)) {
+        if (!BT)
+          BT = new BugType("Pass-by-value argument in function call is "
+                           "undefined", "Logic error");
+        // Generate a report for this bug.
+        EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getName().c_str(),
+                                                     N);
+        R->addRange((*I)->getSourceRange());
+        R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, *I);
+        C.EmitReport(R);
+      }
+    }
+  }
+}
diff --git a/lib/Analysis/UndefinedAssignmentChecker.cpp b/lib/Analysis/UndefinedAssignmentChecker.cpp
new file mode 100644
index 0000000..c5b2401
--- /dev/null
+++ b/lib/Analysis/UndefinedAssignmentChecker.cpp
@@ -0,0 +1,61 @@
+//===--- UndefinedAssignmentChecker.h ---------------------------*- C++ -*--==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines UndefinedAssginmentChecker, a builtin check in GRExprEngine that
+// checks for assigning undefined values.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+
+using namespace clang;
+
+void *UndefinedAssignmentChecker::getTag() {
+  static int x = 0;
+  return &x;
+}
+
+void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C, 
+                                              const Stmt *S,
+                                              SVal location,
+                                              SVal val) {
+  if (!val.isUndef())
+    return;
+
+  ExplodedNode *N = C.GenerateNode(S, true);
+
+  if (!N)
+    return;
+
+  if (!BT)
+    BT = new BugType("Assigned value is garbage or undefined",
+                     "Logic error");
+
+  // Generate a report for this bug.
+  EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getName().c_str(), N);
+  const Expr *ex = 0;
+
+  // FIXME: This check needs to be done on the expression doing the
+  // assignment, not the "store" expression.
+  if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S))
+    ex = B->getRHS();
+  else if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
+    const VarDecl* VD = dyn_cast<VarDecl>(DS->getSingleDecl());
+    ex = VD->getInit();
+  }
+
+  if (ex) {
+    R->addRange(ex->getSourceRange());
+    R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, ex);
+  }
+
+  C.EmitReport(R);
+}  
+
diff --git a/lib/Analysis/VLASizeChecker.cpp b/lib/Analysis/VLASizeChecker.cpp
new file mode 100644
index 0000000..76e4477
--- /dev/null
+++ b/lib/Analysis/VLASizeChecker.cpp
@@ -0,0 +1,102 @@
+//=== VLASizeChecker.cpp - Undefined dereference checker --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines two VLASizeCheckers, a builtin check in GRExprEngine that 
+// performs checks for declaration of VLA of undefined or zero size.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checkers/VLASizeChecker.h"
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+
+using namespace clang;
+
+void *UndefSizedVLAChecker::getTag() {
+  static int x = 0;
+  return &x;
+}
+
+ExplodedNode *UndefSizedVLAChecker::CheckType(QualType T, ExplodedNode *Pred,
+                                              const GRState *state,
+                                              Stmt *S, GRExprEngine &Eng) {
+  GRStmtNodeBuilder &Builder = Eng.getBuilder();
+  BugReporter &BR = Eng.getBugReporter();
+
+  if (VariableArrayType* VLA = dyn_cast<VariableArrayType>(T)) {
+    // FIXME: Handle multi-dimensional VLAs.
+    Expr* SE = VLA->getSizeExpr();
+    SVal Size_untested = state->getSVal(SE);
+
+    if (Size_untested.isUndef()) {
+      if (ExplodedNode* N = Builder.generateNode(S, state, Pred)) {
+        N->markAsSink();
+        if (!BT)
+          BT = new BugType("Declare variable-length array (VLA) of undefined "
+                            "size", "Logic error");
+
+        EnhancedBugReport *R =
+                          new EnhancedBugReport(*BT, BT->getName().c_str(), N);
+        R->addRange(SE->getSourceRange());
+        R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
+        BR.EmitReport(R);
+      }
+      return 0;    
+    }
+  }
+  return Pred;
+}
+
+void *ZeroSizedVLAChecker::getTag() {
+  static int x;
+  return &x;
+}
+
+ExplodedNode *ZeroSizedVLAChecker::CheckType(QualType T, ExplodedNode *Pred, 
+                                             const GRState *state, Stmt *S, 
+                                             GRExprEngine &Eng) {
+  GRStmtNodeBuilder &Builder = Eng.getBuilder();
+  BugReporter &BR = Eng.getBugReporter();
+
+  if (VariableArrayType* VLA = dyn_cast<VariableArrayType>(T)) {
+    // FIXME: Handle multi-dimensional VLAs.
+    Expr* SE = VLA->getSizeExpr();
+    SVal Size_untested = state->getSVal(SE);
+
+    DefinedOrUnknownSVal *Size = dyn_cast<DefinedOrUnknownSVal>(&Size_untested);
+    // Undefined size is checked in another checker.
+    if (!Size)
+      return Pred;
+
+    const GRState *zeroState =  state->Assume(*Size, false);
+    state = state->Assume(*Size, true);
+
+    if (zeroState && !state) {
+      if (ExplodedNode* N = Builder.generateNode(S, zeroState, Pred)) {
+        N->markAsSink();
+        if (!BT)
+          BT = new BugType("Declare variable-length array (VLA) of zero size",
+                            "Logic error");
+
+        EnhancedBugReport *R =
+                          new EnhancedBugReport(*BT, BT->getName().c_str(), N);
+        R->addRange(SE->getSourceRange());
+        R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
+        BR.EmitReport(R);
+      }
+    }
+    if (!state)
+      return 0;
+
+    return Builder.generateNode(S, state, Pred);
+  }
+  else
+    return Pred;
+}
+
-- 
cgit v1.1