From 222e2a7620e6520ffaf4fc4e69d79c18da31542e Mon Sep 17 00:00:00 2001
From: "Zancanaro; Carlo" <czan8762@plang3.cs.usyd.edu.au>
Date: Mon, 24 Sep 2012 09:58:17 +1000
Subject: Add the clang library to the repo (with some of my changes, too).

---
 .../Checkers/.#ArrayBoundCheckerV2_flymake.cpp     |    1 +
 clang/lib/StaticAnalyzer/Checkers/.#CMakeLists.txt |    1 +
 clang/lib/StaticAnalyzer/Checkers/.#Checkers.td    |    1 +
 .../StaticAnalyzer/Checkers/.#DebugCheckers.cpp    |    1 +
 .../Checkers/.#DebugCheckers_flymake.cpp           |    1 +
 .../Checkers/.#DivZeroChecker_flymake.cpp          |    1 +
 .../lib/StaticAnalyzer/Checkers/.#IntervalTest.cpp |    1 +
 .../Checkers/.#IntervalTest_flymake.cpp            |    1 +
 .../Checkers/AdjustedReturnValueChecker.cpp        |   92 +
 .../Checkers/AnalyzerStatsChecker.cpp              |  140 +
 .../StaticAnalyzer/Checkers/ArrayBoundChecker.cpp  |   92 +
 .../Checkers/ArrayBoundCheckerV2.cpp               |  318 ++
 .../StaticAnalyzer/Checkers/AttrNonNullChecker.cpp |  134 +
 .../Checkers/BasicObjCFoundationChecks.cpp         |  672 ++++
 .../Checkers/BoolAssignmentChecker.cpp             |  157 +
 .../Checkers/BuiltinFunctionChecker.cpp            |   82 +
 clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt   |   81 +
 .../lib/StaticAnalyzer/Checkers/CStringChecker.cpp | 1981 +++++++++++
 .../Checkers/CStringSyntaxChecker.cpp              |  191 +
 .../Checkers/CallAndMessageChecker.cpp             |  385 ++
 .../StaticAnalyzer/Checkers/CastSizeChecker.cpp    |   86 +
 .../Checkers/CastToStructChecker.cpp               |   74 +
 .../StaticAnalyzer/Checkers/CheckObjCDealloc.cpp   |  291 ++
 .../Checkers/CheckObjCInstMethSignature.cpp        |  146 +
 .../Checkers/CheckSecuritySyntaxOnly.cpp           |  786 +++++
 .../StaticAnalyzer/Checkers/CheckSizeofPointer.cpp |   92 +
 .../Checkers/CheckerDocumentation.cpp              |  233 ++
 clang/lib/StaticAnalyzer/Checkers/Checkers.td      |  491 +++
 .../lib/StaticAnalyzer/Checkers/ChrootChecker.cpp  |  158 +
 .../lib/StaticAnalyzer/Checkers/ClangCheckers.cpp  |   32 +
 .../lib/StaticAnalyzer/Checkers/ClangSACheckers.h  |   37 +
 .../Checkers/CommonBugCategories.cpp               |   18 +
 .../StaticAnalyzer/Checkers/DeadStoresChecker.cpp  |  386 ++
 .../lib/StaticAnalyzer/Checkers/DebugCheckers.cpp  |  146 +
 .../StaticAnalyzer/Checkers/DereferenceChecker.cpp |  216 ++
 .../lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp |   96 +
 .../Checkers/FixedAddressChecker.cpp               |   67 +
 .../Checkers/GenericTaintChecker.cpp               |  740 ++++
 .../Checkers/IdempotentOperationChecker.cpp        |  747 ++++
 .../lib/StaticAnalyzer/Checkers/InterCheckerAPI.h  |   22 +
 clang/lib/StaticAnalyzer/Checkers/IntervalTest.cpp |   25 +
 .../StaticAnalyzer/Checkers/IteratorsChecker.cpp   |  603 ++++
 .../Checkers/LLVMConventionsChecker.cpp            |  314 ++
 .../Checkers/MacOSKeychainAPIChecker.cpp           |  681 ++++
 .../StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp   |  116 +
 clang/lib/StaticAnalyzer/Checkers/Makefile         |   24 +
 .../lib/StaticAnalyzer/Checkers/MallocChecker.cpp  | 1463 ++++++++
 .../Checkers/MallocOverflowSecurityChecker.cpp     |  267 ++
 .../Checkers/MallocSizeofChecker.cpp               |  211 ++
 .../Checkers/NSAutoreleasePoolChecker.cpp          |   89 +
 .../lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp |  334 ++
 .../Checkers/NoReturnFunctionChecker.cpp           |  146 +
 .../StaticAnalyzer/Checkers/OSAtomicChecker.cpp    |  218 ++
 .../StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp  |   96 +
 .../Checkers/ObjCContainersASTChecker.cpp          |  174 +
 .../Checkers/ObjCContainersChecker.cpp             |  159 +
 .../Checkers/ObjCSelfInitChecker.cpp               |  396 +++
 .../Checkers/ObjCUnusedIVarsChecker.cpp            |  186 +
 .../Checkers/PointerArithChecker.cpp               |   69 +
 .../StaticAnalyzer/Checkers/PointerSubChecker.cpp  |   76 +
 .../StaticAnalyzer/Checkers/PthreadLockChecker.cpp |  198 ++
 .../StaticAnalyzer/Checkers/RetainCountChecker.cpp | 3702 ++++++++++++++++++++
 .../Checkers/ReturnPointerRangeChecker.cpp         |   91 +
 .../StaticAnalyzer/Checkers/ReturnUndefChecker.cpp |   65 +
 .../Checkers/StackAddrEscapeChecker.cpp            |  230 ++
 .../lib/StaticAnalyzer/Checkers/StreamChecker.cpp  |  475 +++
 .../StaticAnalyzer/Checkers/TaintTesterChecker.cpp |   62 +
 .../StaticAnalyzer/Checkers/UndefBranchChecker.cpp |  112 +
 .../Checkers/UndefCapturedBlockVarChecker.cpp      |  105 +
 .../StaticAnalyzer/Checkers/UndefResultChecker.cpp |   91 +
 .../Checkers/UndefinedArraySubscriptChecker.cpp    |   55 +
 .../Checkers/UndefinedAssignmentChecker.cpp        |   88 +
 .../lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp |  353 ++
 .../Checkers/UnreachableCodeChecker.cpp            |  247 ++
 .../lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp |  162 +
 .../StaticAnalyzer/Checkers/VirtualCallChecker.cpp |  241 ++
 76 files changed, 21121 insertions(+)
 create mode 120000 clang/lib/StaticAnalyzer/Checkers/.#ArrayBoundCheckerV2_flymake.cpp
 create mode 120000 clang/lib/StaticAnalyzer/Checkers/.#CMakeLists.txt
 create mode 120000 clang/lib/StaticAnalyzer/Checkers/.#Checkers.td
 create mode 120000 clang/lib/StaticAnalyzer/Checkers/.#DebugCheckers.cpp
 create mode 120000 clang/lib/StaticAnalyzer/Checkers/.#DebugCheckers_flymake.cpp
 create mode 120000 clang/lib/StaticAnalyzer/Checkers/.#DivZeroChecker_flymake.cpp
 create mode 120000 clang/lib/StaticAnalyzer/Checkers/.#IntervalTest.cpp
 create mode 120000 clang/lib/StaticAnalyzer/Checkers/.#IntervalTest_flymake.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/CheckObjCInstMethSignature.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/Checkers.td
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/ClangCheckers.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/ClangSACheckers.h
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/CommonBugCategories.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/IntervalTest.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/Makefile
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp

(limited to 'clang/lib/StaticAnalyzer/Checkers')

diff --git a/clang/lib/StaticAnalyzer/Checkers/.#ArrayBoundCheckerV2_flymake.cpp b/clang/lib/StaticAnalyzer/Checkers/.#ArrayBoundCheckerV2_flymake.cpp
new file mode 120000
index 0000000..235903b
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/.#ArrayBoundCheckerV2_flymake.cpp
@@ -0,0 +1 @@
+carlo@pc-4w14-0.cs.usyd.edu.au.1585:1347012043
\ No newline at end of file
diff --git a/clang/lib/StaticAnalyzer/Checkers/.#CMakeLists.txt b/clang/lib/StaticAnalyzer/Checkers/.#CMakeLists.txt
new file mode 120000
index 0000000..235903b
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/.#CMakeLists.txt
@@ -0,0 +1 @@
+carlo@pc-4w14-0.cs.usyd.edu.au.1585:1347012043
\ No newline at end of file
diff --git a/clang/lib/StaticAnalyzer/Checkers/.#Checkers.td b/clang/lib/StaticAnalyzer/Checkers/.#Checkers.td
new file mode 120000
index 0000000..235903b
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/.#Checkers.td
@@ -0,0 +1 @@
+carlo@pc-4w14-0.cs.usyd.edu.au.1585:1347012043
\ No newline at end of file
diff --git a/clang/lib/StaticAnalyzer/Checkers/.#DebugCheckers.cpp b/clang/lib/StaticAnalyzer/Checkers/.#DebugCheckers.cpp
new file mode 120000
index 0000000..235903b
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/.#DebugCheckers.cpp
@@ -0,0 +1 @@
+carlo@pc-4w14-0.cs.usyd.edu.au.1585:1347012043
\ No newline at end of file
diff --git a/clang/lib/StaticAnalyzer/Checkers/.#DebugCheckers_flymake.cpp b/clang/lib/StaticAnalyzer/Checkers/.#DebugCheckers_flymake.cpp
new file mode 120000
index 0000000..235903b
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/.#DebugCheckers_flymake.cpp
@@ -0,0 +1 @@
+carlo@pc-4w14-0.cs.usyd.edu.au.1585:1347012043
\ No newline at end of file
diff --git a/clang/lib/StaticAnalyzer/Checkers/.#DivZeroChecker_flymake.cpp b/clang/lib/StaticAnalyzer/Checkers/.#DivZeroChecker_flymake.cpp
new file mode 120000
index 0000000..235903b
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/.#DivZeroChecker_flymake.cpp
@@ -0,0 +1 @@
+carlo@pc-4w14-0.cs.usyd.edu.au.1585:1347012043
\ No newline at end of file
diff --git a/clang/lib/StaticAnalyzer/Checkers/.#IntervalTest.cpp b/clang/lib/StaticAnalyzer/Checkers/.#IntervalTest.cpp
new file mode 120000
index 0000000..235903b
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/.#IntervalTest.cpp
@@ -0,0 +1 @@
+carlo@pc-4w14-0.cs.usyd.edu.au.1585:1347012043
\ No newline at end of file
diff --git a/clang/lib/StaticAnalyzer/Checkers/.#IntervalTest_flymake.cpp b/clang/lib/StaticAnalyzer/Checkers/.#IntervalTest_flymake.cpp
new file mode 120000
index 0000000..235903b
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/.#IntervalTest_flymake.cpp
@@ -0,0 +1 @@
+carlo@pc-4w14-0.cs.usyd.edu.au.1585:1347012043
\ No newline at end of file
diff --git a/clang/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp
new file mode 100644
index 0000000..84ea8c7
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp
@@ -0,0 +1,92 @@
+//== AdjustedReturnValueChecker.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 AdjustedReturnValueChecker, a simple check to see if the
+// return value of a function call is different than the one the caller thinks
+// it is.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class AdjustedReturnValueChecker : 
+    public Checker< check::PostStmt<CallExpr> > {
+public:
+  void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
+};
+}
+
+void AdjustedReturnValueChecker::checkPostStmt(const CallExpr *CE,
+                                               CheckerContext &C) const {
+  
+  // Get the result type of the call.
+  QualType expectedResultTy = CE->getType();
+
+  // Fetch the signature of the called function.
+  ProgramStateRef state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
+
+  SVal V = state->getSVal(CE, LCtx);
+  
+  if (V.isUnknown())
+    return;
+  
+  // Casting to void?  Discard the value.
+  if (expectedResultTy->isVoidType()) {
+    C.addTransition(state->BindExpr(CE, LCtx, UnknownVal()));
+    return;
+  }                   
+
+  const MemRegion *callee = state->getSVal(CE->getCallee(), LCtx).getAsRegion();
+  if (!callee)
+    return;
+
+  QualType actualResultTy;
+  
+  if (const FunctionTextRegion *FT = dyn_cast<FunctionTextRegion>(callee)) {
+    const FunctionDecl *FD = FT->getDecl();
+    actualResultTy = FD->getResultType();
+  }
+  else if (const BlockDataRegion *BD = dyn_cast<BlockDataRegion>(callee)) {
+    const BlockTextRegion *BR = BD->getCodeRegion();
+    const BlockPointerType *BT=BR->getLocationType()->getAs<BlockPointerType>();
+    const FunctionType *FT = BT->getPointeeType()->getAs<FunctionType>();
+    actualResultTy = FT->getResultType();
+  }
+
+  // Can this happen?
+  if (actualResultTy.isNull())
+    return;
+
+  // For now, ignore references.
+  if (actualResultTy->getAs<ReferenceType>())
+    return;
+  
+
+  // Are they the same?
+  if (expectedResultTy != actualResultTy) {
+    // FIXME: Do more checking and actual emit an error. At least performing
+    // the cast avoids some assertion failures elsewhere.
+    SValBuilder &svalBuilder = C.getSValBuilder();
+    V = svalBuilder.evalCast(V, expectedResultTy, actualResultTy);
+    C.addTransition(state->BindExpr(CE, LCtx, V));
+  }
+}
+
+void ento::registerAdjustedReturnValueChecker(CheckerManager &mgr) {
+  mgr.registerChecker<AdjustedReturnValueChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp
new file mode 100644
index 0000000..aa6f97b
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp
@@ -0,0 +1,140 @@
+//==--AnalyzerStatsChecker.cpp - Analyzer visitation statistics --*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This file reports various statistics about analyzer visitation.
+//===----------------------------------------------------------------------===//
+#define DEBUG_TYPE "StatsChecker"
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Statistic.h"
+
+using namespace clang;
+using namespace ento;
+
+STATISTIC(NumBlocks,
+          "The # of blocks in top level functions");
+STATISTIC(NumBlocksUnreachable,
+          "The # of unreachable blocks in analyzing top level functions");
+
+namespace {
+class AnalyzerStatsChecker : public Checker<check::EndAnalysis> {
+public:
+  void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const;
+};
+}
+
+void AnalyzerStatsChecker::checkEndAnalysis(ExplodedGraph &G,
+                                            BugReporter &B,
+                                            ExprEngine &Eng) const {
+  const CFG *C  = 0;
+  const SourceManager &SM = B.getSourceManager();
+  llvm::SmallPtrSet<const CFGBlock*, 256> reachable;
+
+  // Root node should have the location context of the top most function.
+  const ExplodedNode *GraphRoot = *G.roots_begin();
+  const LocationContext *LC = GraphRoot->getLocation().getLocationContext();
+
+  const Decl *D = LC->getDecl();
+
+  // Iterate over the exploded graph.
+  for (ExplodedGraph::node_iterator I = G.nodes_begin();
+      I != G.nodes_end(); ++I) {
+    const ProgramPoint &P = I->getLocation();
+
+    // Only check the coverage in the top level function (optimization).
+    if (D != P.getLocationContext()->getDecl())
+      continue;
+
+    if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) {
+      const CFGBlock *CB = BE->getBlock();
+      reachable.insert(CB);
+    }
+  }
+
+  // Get the CFG and the Decl of this block.
+  C = LC->getCFG();
+
+  unsigned total = 0, unreachable = 0;
+
+  // Find CFGBlocks that were not covered by any node
+  for (CFG::const_iterator I = C->begin(); I != C->end(); ++I) {
+    const CFGBlock *CB = *I;
+    ++total;
+    // Check if the block is unreachable
+    if (!reachable.count(CB)) {
+      ++unreachable;
+    }
+  }
+
+  // We never 'reach' the entry block, so correct the unreachable count
+  unreachable--;
+  // There is no BlockEntrance corresponding to the exit block as well, so
+  // assume it is reached as well.
+  unreachable--;
+
+  // Generate the warning string
+  SmallString<128> buf;
+  llvm::raw_svector_ostream output(buf);
+  PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());
+  if (!Loc.isValid())
+    return;
+
+  if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
+    const NamedDecl *ND = cast<NamedDecl>(D);
+    output << *ND;
+  }
+  else if (isa<BlockDecl>(D)) {
+    output << "block(line:" << Loc.getLine() << ":col:" << Loc.getColumn();
+  }
+  
+  NumBlocksUnreachable += unreachable;
+  NumBlocks += total;
+  std::string NameOfRootFunction = output.str();
+
+  output << " -> Total CFGBlocks: " << total << " | Unreachable CFGBlocks: "
+      << unreachable << " | Exhausted Block: "
+      << (Eng.wasBlocksExhausted() ? "yes" : "no")
+      << " | Empty WorkList: "
+      << (Eng.hasEmptyWorkList() ? "yes" : "no");
+
+  B.EmitBasicReport(D, "Analyzer Statistics", "Internal Statistics",
+                    output.str(), PathDiagnosticLocation(D, SM));
+
+  // Emit warning for each block we bailed out on.
+  typedef CoreEngine::BlocksExhausted::const_iterator ExhaustedIterator;
+  const CoreEngine &CE = Eng.getCoreEngine();
+  for (ExhaustedIterator I = CE.blocks_exhausted_begin(),
+      E = CE.blocks_exhausted_end(); I != E; ++I) {
+    const BlockEdge &BE =  I->first;
+    const CFGBlock *Exit = BE.getDst();
+    const CFGElement &CE = Exit->front();
+    if (const CFGStmt *CS = dyn_cast<CFGStmt>(&CE)) {
+      SmallString<128> bufI;
+      llvm::raw_svector_ostream outputI(bufI);
+      outputI << "(" << NameOfRootFunction << ")" <<
+                 ": The analyzer generated a sink at this point";
+      B.EmitBasicReport(D, "Sink Point", "Internal Statistics", outputI.str(),
+                        PathDiagnosticLocation::createBegin(CS->getStmt(),
+                                                            SM, LC));
+    }
+  }
+}
+
+void ento::registerAnalyzerStatsChecker(CheckerManager &mgr) {
+  mgr.registerChecker<AnalyzerStatsChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
new file mode 100644
index 0000000..b2ad184
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
@@ -0,0 +1,92 @@
+//== ArrayBoundChecker.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 ArrayBoundChecker, which is a path-sensitive check
+// which looks for an out-of-bound array element access.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class ArrayBoundChecker : 
+    public Checker<check::Location> {
+  mutable OwningPtr<BuiltinBug> BT;
+public:
+  void checkLocation(SVal l, bool isLoad, const Stmt* S,
+                     CheckerContext &C) const;
+};
+}
+
+void ArrayBoundChecker::checkLocation(SVal l, bool isLoad, const Stmt* LoadS,
+                                      CheckerContext &C) const {
+  // Check for out of bound array element access.
+  const MemRegion *R = l.getAsRegion();
+  if (!R)
+    return;
+
+  const ElementRegion *ER = dyn_cast<ElementRegion>(R);
+  if (!ER)
+    return;
+
+  // Get the index of the accessed element.
+  DefinedOrUnknownSVal Idx = cast<DefinedOrUnknownSVal>(ER->getIndex());
+
+  // Zero index is always in bound, this also passes ElementRegions created for
+  // pointer casts.
+  if (Idx.isZeroConstant())
+    return;
+
+  ProgramStateRef state = C.getState();
+
+  // Get the size of the array.
+  DefinedOrUnknownSVal NumElements 
+    = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(), 
+                                            ER->getValueType());
+
+  ProgramStateRef StInBound = state->assumeInBound(Idx, NumElements, true);
+  ProgramStateRef StOutBound = state->assumeInBound(Idx, NumElements, false);
+  if (StOutBound && !StInBound) {
+    ExplodedNode *N = C.generateSink(StOutBound);
+    if (!N)
+      return;
+  
+    if (!BT)
+      BT.reset(new BuiltinBug("Out-of-bound array access",
+                       "Access out-of-bound array element (buffer overflow)"));
+
+    // FIXME: It would be nice to eventually make this diagnostic more clear,
+    // e.g., by referencing the original declaration or by saying *why* this
+    // reference is outside the range.
+
+    // Generate a report for this bug.
+    BugReport *report = 
+      new BugReport(*BT, BT->getDescription(), N);
+
+    report->addRange(LoadS->getSourceRange());
+    C.EmitReport(report);
+    return;
+  }
+  
+  // Array bound check succeeded.  From this point forward the array bound
+  // should always succeed.
+  C.addTransition(StInBound);
+}
+
+void ento::registerArrayBoundChecker(CheckerManager &mgr) {
+  mgr.registerChecker<ArrayBoundChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp b/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
new file mode 100644
index 0000000..c6efe94
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
@@ -0,0 +1,318 @@
+//== ArrayBoundCheckerV2.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 ArrayBoundCheckerV2, which is a path-sensitive check
+// which looks for an out-of-bound array element access.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/AST/CharUnits.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/STLExtras.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class ArrayBoundCheckerV2 : 
+    public Checker<check::Location> {
+  mutable OwningPtr<BuiltinBug> BT;
+      
+  enum OOB_Kind { OOB_Precedes, OOB_Excedes, OOB_Tainted };
+  
+  void reportOOB(CheckerContext &C, ProgramStateRef errorState,
+                 OOB_Kind kind) const;
+      
+public:
+  void checkLocation(SVal l, bool isLoad, const Stmt*S,
+                     CheckerContext &C) const;
+};
+
+// FIXME: Eventually replace RegionRawOffset with this class.
+class RegionRawOffsetV2 {
+private:
+  const SubRegion *baseRegion;
+  SVal byteOffset;
+  
+  RegionRawOffsetV2()
+    : baseRegion(0), byteOffset(UnknownVal()) {}
+
+public:
+  RegionRawOffsetV2(const SubRegion* base, SVal offset)
+    : baseRegion(base), byteOffset(offset) {}
+
+  NonLoc getByteOffset() const { return cast<NonLoc>(byteOffset); }
+  const SubRegion *getRegion() const { return baseRegion; }
+  
+  static RegionRawOffsetV2 computeOffset(ProgramStateRef state,
+                                         SValBuilder &svalBuilder,
+                                         SVal location);
+
+  void dump() const;
+  void dumpToStream(raw_ostream &os) const;
+};
+}
+
+static SVal computeExtentBegin(SValBuilder &svalBuilder, 
+                               const MemRegion *region) {
+  while (true)
+    switch (region->getKind()) {
+      default:
+        return svalBuilder.makeZeroArrayIndex();        
+      case MemRegion::SymbolicRegionKind:
+        // FIXME: improve this later by tracking symbolic lower bounds
+        // for symbolic regions.
+        return UnknownVal();
+      case MemRegion::ElementRegionKind:
+        region = cast<SubRegion>(region)->getSuperRegion();
+        continue;
+    }
+}
+
+void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
+                                        const Stmt* LoadS,
+                                        CheckerContext &checkerContext) const {
+
+  // NOTE: Instead of using ProgramState::assumeInBound(), we are prototyping
+  // some new logic here that reasons directly about memory region extents.
+  // Once that logic is more mature, we can bring it back to assumeInBound()
+  // for all clients to use.
+  //
+  // The algorithm we are using here for bounds checking is to see if the
+  // memory access is within the extent of the base region.  Since we
+  // have some flexibility in defining the base region, we can achieve
+  // various levels of conservatism in our buffer overflow checking.
+  ProgramStateRef state = checkerContext.getState();  
+  ProgramStateRef originalState = state;
+
+  SValBuilder &svalBuilder = checkerContext.getSValBuilder();
+  const RegionRawOffsetV2 &rawOffset = 
+    RegionRawOffsetV2::computeOffset(state, svalBuilder, location);
+
+  if (!rawOffset.getRegion())
+    return;
+
+  // CHECK LOWER BOUND: Is byteOffset < extent begin?  
+  //  If so, we are doing a load/store
+  //  before the first valid offset in the memory region.
+
+  SVal extentBegin = computeExtentBegin(svalBuilder, rawOffset.getRegion());
+  
+  if (isa<NonLoc>(extentBegin)) {
+    SVal lowerBound
+      = svalBuilder.evalBinOpNN(state, BO_LT, rawOffset.getByteOffset(),
+                                cast<NonLoc>(extentBegin),
+                                svalBuilder.getConditionType());
+
+    NonLoc *lowerBoundToCheck = dyn_cast<NonLoc>(&lowerBound);
+    if (!lowerBoundToCheck)
+      return;
+    
+    ProgramStateRef state_precedesLowerBound, state_withinLowerBound;
+    llvm::tie(state_precedesLowerBound, state_withinLowerBound) =
+      state->assume(*lowerBoundToCheck);
+
+    // Are we constrained enough to definitely precede the lower bound?
+    if (state_precedesLowerBound && !state_withinLowerBound) {
+      reportOOB(checkerContext, state_precedesLowerBound, OOB_Precedes);
+      return;
+    }
+  
+    // Otherwise, assume the constraint of the lower bound.
+    assert(state_withinLowerBound);
+    state = state_withinLowerBound;
+  }
+  
+  do {
+    // CHECK UPPER BOUND: Is byteOffset >= extent(baseRegion)?  If so,
+    // we are doing a load/store after the last valid offset.
+    DefinedOrUnknownSVal extentVal =
+      rawOffset.getRegion()->getExtent(svalBuilder);
+    if (!isa<NonLoc>(extentVal))
+      break;
+
+    SVal upperbound
+      = svalBuilder.evalBinOpNN(state, BO_GE, rawOffset.getByteOffset(),
+                                cast<NonLoc>(extentVal),
+                                svalBuilder.getConditionType());
+  
+    NonLoc *upperboundToCheck = dyn_cast<NonLoc>(&upperbound);
+    if (!upperboundToCheck)
+      break;
+  
+    ProgramStateRef state_exceedsUpperBound, state_withinUpperBound;
+    llvm::tie(state_exceedsUpperBound, state_withinUpperBound) =
+      state->assume(*upperboundToCheck);
+
+    // If we are under constrained and the index variables are tainted, report.
+    if (state_exceedsUpperBound && state_withinUpperBound) {
+      if (state->isTainted(rawOffset.getByteOffset()))
+        reportOOB(checkerContext, state_exceedsUpperBound, OOB_Tainted);
+        return;
+    }
+  
+    // If we are constrained enough to definitely exceed the upper bound, report.
+    if (state_exceedsUpperBound) {
+      assert(!state_withinUpperBound);
+      reportOOB(checkerContext, state_exceedsUpperBound, OOB_Excedes);
+      return;
+    }
+  
+    assert(state_withinUpperBound);
+    state = state_withinUpperBound;
+  }
+  while (false);
+  
+  if (state != originalState)
+    checkerContext.addTransition(state);
+}
+
+void ArrayBoundCheckerV2::reportOOB(CheckerContext &checkerContext,
+                                    ProgramStateRef errorState,
+                                    OOB_Kind kind) const {
+  
+  ExplodedNode *errorNode = checkerContext.generateSink(errorState);
+  if (!errorNode)
+    return;
+
+  if (!BT)
+    BT.reset(new BuiltinBug("Out-of-bound access"));
+
+  // FIXME: This diagnostics are preliminary.  We should get far better
+  // diagnostics for explaining buffer overruns.
+
+  SmallString<256> buf;
+  llvm::raw_svector_ostream os(buf);
+  os << "Out of bound memory access ";
+  switch (kind) {
+  case OOB_Precedes:
+    os << "(accessed memory precedes memory block)";
+    break;
+  case OOB_Excedes:
+    os << "(access exceeds upper limit of memory block)";
+    break;
+  case OOB_Tainted:
+    os << "(index is tainted)";
+    break;
+  }
+
+  checkerContext.EmitReport(new BugReport(*BT, os.str(), errorNode));
+}
+
+void RegionRawOffsetV2::dump() const {
+  dumpToStream(llvm::errs());
+}
+
+void RegionRawOffsetV2::dumpToStream(raw_ostream &os) const {
+  os << "raw_offset_v2{" << getRegion() << ',' << getByteOffset() << '}';
+}
+
+// FIXME: Merge with the implementation of the same method in Store.cpp
+static bool IsCompleteType(ASTContext &Ctx, QualType Ty) {
+  if (const RecordType *RT = Ty->getAs<RecordType>()) {
+    const RecordDecl *D = RT->getDecl();
+    if (!D->getDefinition())
+      return false;
+  }
+
+  return true;
+}
+
+
+// Lazily computes a value to be used by 'computeOffset'.  If 'val'
+// is unknown or undefined, we lazily substitute '0'.  Otherwise,
+// return 'val'.
+static inline SVal getValue(SVal val, SValBuilder &svalBuilder) {
+  return isa<UndefinedVal>(val) ? svalBuilder.makeArrayIndex(0) : val;
+}
+
+// Scale a base value by a scaling factor, and return the scaled
+// value as an SVal.  Used by 'computeOffset'.
+static inline SVal scaleValue(ProgramStateRef state,
+                              NonLoc baseVal, CharUnits scaling,
+                              SValBuilder &sb) {
+  return sb.evalBinOpNN(state, BO_Mul, baseVal,
+                        sb.makeArrayIndex(scaling.getQuantity()),
+                        sb.getArrayIndexType());
+}
+
+// Add an SVal to another, treating unknown and undefined values as
+// summing to UnknownVal.  Used by 'computeOffset'.
+static SVal addValue(ProgramStateRef state, SVal x, SVal y,
+                     SValBuilder &svalBuilder) {
+  // We treat UnknownVals and UndefinedVals the same here because we
+  // only care about computing offsets.
+  if (x.isUnknownOrUndef() || y.isUnknownOrUndef())
+    return UnknownVal();
+  
+  return svalBuilder.evalBinOpNN(state, BO_Add,                                 
+                                 cast<NonLoc>(x), cast<NonLoc>(y),
+                                 svalBuilder.getArrayIndexType());
+}
+
+/// Compute a raw byte offset from a base region.  Used for array bounds
+/// checking.
+RegionRawOffsetV2 RegionRawOffsetV2::computeOffset(ProgramStateRef state,
+                                                   SValBuilder &svalBuilder,
+                                                   SVal location)
+{
+  const MemRegion *region = location.getAsRegion();
+  SVal offset = UndefinedVal();
+  
+  while (region) {
+    switch (region->getKind()) {
+      default: {
+        if (const SubRegion *subReg = dyn_cast<SubRegion>(region)) {
+          offset = getValue(offset, svalBuilder);
+          if (!offset.isUnknownOrUndef())
+            return RegionRawOffsetV2(subReg, offset);
+        }
+        return RegionRawOffsetV2();
+      }
+      case MemRegion::ElementRegionKind: {
+        const ElementRegion *elemReg = cast<ElementRegion>(region);
+        SVal index = elemReg->getIndex();
+        if (!isa<NonLoc>(index))
+          return RegionRawOffsetV2();
+        QualType elemType = elemReg->getElementType();
+        // If the element is an incomplete type, go no further.
+        ASTContext &astContext = svalBuilder.getContext();
+        if (!IsCompleteType(astContext, elemType))
+          return RegionRawOffsetV2();
+        
+        // Update the offset.
+        offset = addValue(state,
+                          getValue(offset, svalBuilder),
+                          scaleValue(state,
+                          cast<NonLoc>(index),
+                          astContext.getTypeSizeInChars(elemType),
+                          svalBuilder),
+                          svalBuilder);
+
+        if (offset.isUnknownOrUndef())
+          return RegionRawOffsetV2();
+
+        region = elemReg->getSuperRegion();
+        continue;
+      }
+    }
+  }
+  return RegionRawOffsetV2();
+}
+
+
+void ento::registerArrayBoundCheckerV2(CheckerManager &mgr) {
+  mgr.registerChecker<ArrayBoundCheckerV2>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp
new file mode 100644
index 0000000..ab66e98
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp
@@ -0,0 +1,134 @@
+//===--- 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 ExprEngine that 
+// performs checks for arguments declared to have nonnull attribute.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class AttrNonNullChecker
+  : public Checker< check::PreStmt<CallExpr> > {
+  mutable OwningPtr<BugType> BT;
+public:
+
+  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
+};
+} // end anonymous namespace
+
+void AttrNonNullChecker::checkPreStmt(const CallExpr *CE,
+                                      CheckerContext &C) const {
+  ProgramStateRef state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
+
+  // Check if the callee has a 'nonnull' attribute.
+  SVal X = state->getSVal(CE->getCallee(), LCtx);
+
+  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;
+
+    SVal V = state->getSVal(*I, LCtx);
+    DefinedSVal *DV = dyn_cast<DefinedSVal>(&V);
+
+    // If the value is unknown or undefined, we can't perform this check.
+    if (!DV)
+      continue;
+
+    if (!isa<Loc>(*DV)) {
+      // If the argument is a union type, we want to handle a potential
+      // transparent_unoin GCC extension.
+      QualType T = (*I)->getType();
+      const RecordType *UT = T->getAsUnionType();
+      if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>())
+        continue;
+      if (nonloc::CompoundVal *CSV = dyn_cast<nonloc::CompoundVal>(DV)) {
+        nonloc::CompoundVal::iterator CSV_I = CSV->begin();
+        assert(CSV_I != CSV->end());
+        V = *CSV_I;
+        DV = dyn_cast<DefinedSVal>(&V);
+        assert(++CSV_I == CSV->end());
+        if (!DV)
+          continue;        
+      }
+      else {
+        // FIXME: Handle LazyCompoundVals?
+        continue;
+      }
+    }
+
+    ConstraintManager &CM = C.getConstraintManager();
+    ProgramStateRef 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.generateSink(stateNull)) {
+
+        // 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.reset(new BugType("Argument with 'nonnull' attribute passed null",
+                               "API"));
+
+        BugReport *R =
+          new BugReport(*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->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(errorNode,
+                                                                   arg, R));
+        // 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.
+  C.addTransition(state);
+}
+
+void ento::registerAttrNonNullChecker(CheckerManager &mgr) {
+  mgr.registerChecker<AttrNonNullChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
new file mode 100644
index 0000000..6dd0a8c
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
@@ -0,0 +1,672 @@
+//== BasicObjCFoundationChecks.cpp - Simple Apple-Foundation checks -*- 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 BasicObjCFoundationChecks, a class that encapsulates
+//  a set of simple checks to run on Objective-C code using Apple's Foundation
+//  classes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ASTContext.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class APIMisuse : public BugType {
+public:
+  APIMisuse(const char* name) : BugType(name, "API Misuse (Apple)") {}
+};
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Utility functions.
+//===----------------------------------------------------------------------===//
+
+static const char* GetReceiverNameType(const ObjCMessage &msg) {
+  if (const ObjCInterfaceDecl *ID = msg.getReceiverInterface())
+    return ID->getIdentifier()->getNameStart();
+  return 0;
+}
+
+static bool isReceiverClassOrSuperclass(const ObjCInterfaceDecl *ID,
+                                        StringRef ClassName) {
+  if (ID->getIdentifier()->getName() == ClassName)
+    return true;
+
+  if (const ObjCInterfaceDecl *Super = ID->getSuperClass())
+    return isReceiverClassOrSuperclass(Super, ClassName);
+
+  return false;
+}
+
+static inline bool isNil(SVal X) {
+  return isa<loc::ConcreteInt>(X);
+}
+
+//===----------------------------------------------------------------------===//
+// NilArgChecker - Check for prohibited nil arguments to ObjC method calls.
+//===----------------------------------------------------------------------===//
+
+namespace {
+  class NilArgChecker : public Checker<check::PreObjCMessage> {
+    mutable OwningPtr<APIMisuse> BT;
+
+    void WarnNilArg(CheckerContext &C,
+                    const ObjCMessage &msg, unsigned Arg) const;
+
+  public:
+    void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const;
+  };
+}
+
+void NilArgChecker::WarnNilArg(CheckerContext &C,
+                               const ObjCMessage &msg,
+                               unsigned int Arg) const
+{
+  if (!BT)
+    BT.reset(new APIMisuse("nil argument"));
+  
+  if (ExplodedNode *N = C.generateSink()) {
+    SmallString<128> sbuf;
+    llvm::raw_svector_ostream os(sbuf);
+    os << "Argument to '" << GetReceiverNameType(msg) << "' method '"
+       << msg.getSelector().getAsString() << "' cannot be nil";
+
+    BugReport *R = new BugReport(*BT, os.str(), N);
+    R->addRange(msg.getArgSourceRange(Arg));
+    C.EmitReport(R);
+  }
+}
+
+void NilArgChecker::checkPreObjCMessage(ObjCMessage msg,
+                                        CheckerContext &C) const {
+  const ObjCInterfaceDecl *ID = msg.getReceiverInterface();
+  if (!ID)
+    return;
+  
+  if (isReceiverClassOrSuperclass(ID, "NSString")) {
+    Selector S = msg.getSelector();
+    
+    if (S.isUnarySelector())
+      return;
+    
+    // FIXME: This is going to be really slow doing these checks with
+    //  lexical comparisons.
+    
+    std::string NameStr = S.getAsString();
+    StringRef Name(NameStr);
+    assert(!Name.empty());
+    
+    // FIXME: Checking for initWithFormat: will not work in most cases
+    //  yet because [NSString alloc] returns id, not NSString*.  We will
+    //  need support for tracking expected-type information in the analyzer
+    //  to find these errors.
+    if (Name == "caseInsensitiveCompare:" ||
+        Name == "compare:" ||
+        Name == "compare:options:" ||
+        Name == "compare:options:range:" ||
+        Name == "compare:options:range:locale:" ||
+        Name == "componentsSeparatedByCharactersInSet:" ||
+        Name == "initWithFormat:") {
+      if (isNil(msg.getArgSVal(0, C.getLocationContext(), C.getState())))
+        WarnNilArg(C, msg, 0);
+    }
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// Error reporting.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class CFNumberCreateChecker : public Checker< check::PreStmt<CallExpr> > {
+  mutable OwningPtr<APIMisuse> BT;
+  mutable IdentifierInfo* II;
+public:
+  CFNumberCreateChecker() : II(0) {}
+
+  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
+
+private:
+  void EmitError(const TypedRegion* R, const Expr *Ex,
+                uint64_t SourceSize, uint64_t TargetSize, uint64_t NumberKind);
+};
+} // end anonymous namespace
+
+enum CFNumberType {
+  kCFNumberSInt8Type = 1,
+  kCFNumberSInt16Type = 2,
+  kCFNumberSInt32Type = 3,
+  kCFNumberSInt64Type = 4,
+  kCFNumberFloat32Type = 5,
+  kCFNumberFloat64Type = 6,
+  kCFNumberCharType = 7,
+  kCFNumberShortType = 8,
+  kCFNumberIntType = 9,
+  kCFNumberLongType = 10,
+  kCFNumberLongLongType = 11,
+  kCFNumberFloatType = 12,
+  kCFNumberDoubleType = 13,
+  kCFNumberCFIndexType = 14,
+  kCFNumberNSIntegerType = 15,
+  kCFNumberCGFloatType = 16
+};
+
+namespace {
+  template<typename T>
+  class Optional {
+    bool IsKnown;
+    T Val;
+  public:
+    Optional() : IsKnown(false), Val(0) {}
+    Optional(const T& val) : IsKnown(true), Val(val) {}
+
+    bool isKnown() const { return IsKnown; }
+
+    const T& getValue() const {
+      assert (isKnown());
+      return Val;
+    }
+
+    operator const T&() const {
+      return getValue();
+    }
+  };
+}
+
+static Optional<uint64_t> GetCFNumberSize(ASTContext &Ctx, uint64_t i) {
+  static const unsigned char FixedSize[] = { 8, 16, 32, 64, 32, 64 };
+
+  if (i < kCFNumberCharType)
+    return FixedSize[i-1];
+
+  QualType T;
+
+  switch (i) {
+    case kCFNumberCharType:     T = Ctx.CharTy;     break;
+    case kCFNumberShortType:    T = Ctx.ShortTy;    break;
+    case kCFNumberIntType:      T = Ctx.IntTy;      break;
+    case kCFNumberLongType:     T = Ctx.LongTy;     break;
+    case kCFNumberLongLongType: T = Ctx.LongLongTy; break;
+    case kCFNumberFloatType:    T = Ctx.FloatTy;    break;
+    case kCFNumberDoubleType:   T = Ctx.DoubleTy;   break;
+    case kCFNumberCFIndexType:
+    case kCFNumberNSIntegerType:
+    case kCFNumberCGFloatType:
+      // FIXME: We need a way to map from names to Type*.
+    default:
+      return Optional<uint64_t>();
+  }
+
+  return Ctx.getTypeSize(T);
+}
+
+#if 0
+static const char* GetCFNumberTypeStr(uint64_t i) {
+  static const char* Names[] = {
+    "kCFNumberSInt8Type",
+    "kCFNumberSInt16Type",
+    "kCFNumberSInt32Type",
+    "kCFNumberSInt64Type",
+    "kCFNumberFloat32Type",
+    "kCFNumberFloat64Type",
+    "kCFNumberCharType",
+    "kCFNumberShortType",
+    "kCFNumberIntType",
+    "kCFNumberLongType",
+    "kCFNumberLongLongType",
+    "kCFNumberFloatType",
+    "kCFNumberDoubleType",
+    "kCFNumberCFIndexType",
+    "kCFNumberNSIntegerType",
+    "kCFNumberCGFloatType"
+  };
+
+  return i <= kCFNumberCGFloatType ? Names[i-1] : "Invalid CFNumberType";
+}
+#endif
+
+void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
+                                         CheckerContext &C) const {
+  ProgramStateRef state = C.getState();
+  const FunctionDecl *FD = C.getCalleeDecl(CE);
+  if (!FD)
+    return;
+  
+  ASTContext &Ctx = C.getASTContext();
+  if (!II)
+    II = &Ctx.Idents.get("CFNumberCreate");
+
+  if (FD->getIdentifier() != II || CE->getNumArgs() != 3)
+    return;
+
+  // Get the value of the "theType" argument.
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal TheTypeVal = state->getSVal(CE->getArg(1), LCtx);
+
+  // FIXME: We really should allow ranges of valid theType values, and
+  //   bifurcate the state appropriately.
+  nonloc::ConcreteInt* V = dyn_cast<nonloc::ConcreteInt>(&TheTypeVal);
+  if (!V)
+    return;
+
+  uint64_t NumberKind = V->getValue().getLimitedValue();
+  Optional<uint64_t> TargetSize = GetCFNumberSize(Ctx, NumberKind);
+
+  // FIXME: In some cases we can emit an error.
+  if (!TargetSize.isKnown())
+    return;
+
+  // Look at the value of the integer being passed by reference.  Essentially
+  // we want to catch cases where the value passed in is not equal to the
+  // size of the type being created.
+  SVal TheValueExpr = state->getSVal(CE->getArg(2), LCtx);
+
+  // FIXME: Eventually we should handle arbitrary locations.  We can do this
+  //  by having an enhanced memory model that does low-level typing.
+  loc::MemRegionVal* LV = dyn_cast<loc::MemRegionVal>(&TheValueExpr);
+  if (!LV)
+    return;
+
+  const TypedValueRegion* R = dyn_cast<TypedValueRegion>(LV->stripCasts());
+  if (!R)
+    return;
+
+  QualType T = Ctx.getCanonicalType(R->getValueType());
+
+  // FIXME: If the pointee isn't an integer type, should we flag a warning?
+  //  People can do weird stuff with pointers.
+
+  if (!T->isIntegerType())
+    return;
+
+  uint64_t SourceSize = Ctx.getTypeSize(T);
+
+  // CHECK: is SourceSize == TargetSize
+  if (SourceSize == TargetSize)
+    return;
+
+  // Generate an error.  Only generate a sink if 'SourceSize < TargetSize';
+  // otherwise generate a regular node.
+  //
+  // FIXME: We can actually create an abstract "CFNumber" object that has
+  //  the bits initialized to the provided values.
+  //
+  if (ExplodedNode *N = SourceSize < TargetSize ? C.generateSink() 
+                                                : C.addTransition()) {
+    SmallString<128> sbuf;
+    llvm::raw_svector_ostream os(sbuf);
+    
+    os << (SourceSize == 8 ? "An " : "A ")
+       << SourceSize << " bit integer is used to initialize a CFNumber "
+                        "object that represents "
+       << (TargetSize == 8 ? "an " : "a ")
+       << TargetSize << " bit integer. ";
+    
+    if (SourceSize < TargetSize)
+      os << (TargetSize - SourceSize)
+      << " bits of the CFNumber value will be garbage." ;
+    else
+      os << (SourceSize - TargetSize)
+      << " bits of the input integer will be lost.";
+
+    if (!BT)
+      BT.reset(new APIMisuse("Bad use of CFNumberCreate"));
+    
+    BugReport *report = new BugReport(*BT, os.str(), N);
+    report->addRange(CE->getArg(2)->getSourceRange());
+    C.EmitReport(report);
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// CFRetain/CFRelease checking for null arguments.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class CFRetainReleaseChecker : public Checker< check::PreStmt<CallExpr> > {
+  mutable OwningPtr<APIMisuse> BT;
+  mutable IdentifierInfo *Retain, *Release;
+public:
+  CFRetainReleaseChecker(): Retain(0), Release(0) {}
+  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
+};
+} // end anonymous namespace
+
+
+void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE,
+                                          CheckerContext &C) const {
+  // If the CallExpr doesn't have exactly 1 argument just give up checking.
+  if (CE->getNumArgs() != 1)
+    return;
+
+  ProgramStateRef state = C.getState();
+  const FunctionDecl *FD = C.getCalleeDecl(CE);
+  if (!FD)
+    return;
+  
+  if (!BT) {
+    ASTContext &Ctx = C.getASTContext();
+    Retain = &Ctx.Idents.get("CFRetain");
+    Release = &Ctx.Idents.get("CFRelease");
+    BT.reset(new APIMisuse("null passed to CFRetain/CFRelease"));
+  }
+
+  // Check if we called CFRetain/CFRelease.
+  const IdentifierInfo *FuncII = FD->getIdentifier();
+  if (!(FuncII == Retain || FuncII == Release))
+    return;
+
+  // FIXME: The rest of this just checks that the argument is non-null.
+  // It should probably be refactored and combined with AttrNonNullChecker.
+
+  // Get the argument's value.
+  const Expr *Arg = CE->getArg(0);
+  SVal ArgVal = state->getSVal(Arg, C.getLocationContext());
+  DefinedSVal *DefArgVal = dyn_cast<DefinedSVal>(&ArgVal);
+  if (!DefArgVal)
+    return;
+
+  // Get a NULL value.
+  SValBuilder &svalBuilder = C.getSValBuilder();
+  DefinedSVal zero = cast<DefinedSVal>(svalBuilder.makeZeroVal(Arg->getType()));
+
+  // Make an expression asserting that they're equal.
+  DefinedOrUnknownSVal ArgIsNull = svalBuilder.evalEQ(state, zero, *DefArgVal);
+
+  // Are they equal?
+  ProgramStateRef stateTrue, stateFalse;
+  llvm::tie(stateTrue, stateFalse) = state->assume(ArgIsNull);
+
+  if (stateTrue && !stateFalse) {
+    ExplodedNode *N = C.generateSink(stateTrue);
+    if (!N)
+      return;
+
+    const char *description = (FuncII == Retain)
+                            ? "Null pointer argument in call to CFRetain"
+                            : "Null pointer argument in call to CFRelease";
+
+    BugReport *report = new BugReport(*BT, description, N);
+    report->addRange(Arg->getSourceRange());
+    report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Arg,
+                                                                    report));
+    C.EmitReport(report);
+    return;
+  }
+
+  // From here on, we know the argument is non-null.
+  C.addTransition(stateFalse);
+}
+
+//===----------------------------------------------------------------------===//
+// Check for sending 'retain', 'release', or 'autorelease' directly to a Class.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class ClassReleaseChecker : public Checker<check::PreObjCMessage> {
+  mutable Selector releaseS;
+  mutable Selector retainS;
+  mutable Selector autoreleaseS;
+  mutable Selector drainS;
+  mutable OwningPtr<BugType> BT;
+
+public:
+  void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const;
+};
+}
+
+void ClassReleaseChecker::checkPreObjCMessage(ObjCMessage msg,
+                                              CheckerContext &C) const {
+  
+  if (!BT) {
+    BT.reset(new APIMisuse("message incorrectly sent to class instead of class "
+                           "instance"));
+  
+    ASTContext &Ctx = C.getASTContext();
+    releaseS = GetNullarySelector("release", Ctx);
+    retainS = GetNullarySelector("retain", Ctx);
+    autoreleaseS = GetNullarySelector("autorelease", Ctx);
+    drainS = GetNullarySelector("drain", Ctx);
+  }
+  
+  if (msg.isInstanceMessage())
+    return;
+  const ObjCInterfaceDecl *Class = msg.getReceiverInterface();
+  assert(Class);
+
+  Selector S = msg.getSelector();
+  if (!(S == releaseS || S == retainS || S == autoreleaseS || S == drainS))
+    return;
+  
+  if (ExplodedNode *N = C.addTransition()) {
+    SmallString<200> buf;
+    llvm::raw_svector_ostream os(buf);
+
+    os << "The '" << S.getAsString() << "' message should be sent to instances "
+          "of class '" << Class->getName()
+       << "' and not the class directly";
+  
+    BugReport *report = new BugReport(*BT, os.str(), N);
+    report->addRange(msg.getSourceRange());
+    C.EmitReport(report);
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// Check for passing non-Objective-C types to variadic methods that expect
+// only Objective-C types.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class VariadicMethodTypeChecker : public Checker<check::PreObjCMessage> {
+  mutable Selector arrayWithObjectsS;
+  mutable Selector dictionaryWithObjectsAndKeysS;
+  mutable Selector setWithObjectsS;
+  mutable Selector orderedSetWithObjectsS;
+  mutable Selector initWithObjectsS;
+  mutable Selector initWithObjectsAndKeysS;
+  mutable OwningPtr<BugType> BT;
+
+  bool isVariadicMessage(const ObjCMessage &msg) const;
+
+public:
+  void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const;
+};
+}
+
+/// isVariadicMessage - Returns whether the given message is a variadic message,
+/// where all arguments must be Objective-C types.
+bool
+VariadicMethodTypeChecker::isVariadicMessage(const ObjCMessage &msg) const {
+  const ObjCMethodDecl *MD = msg.getMethodDecl();
+  
+  if (!MD || !MD->isVariadic() || isa<ObjCProtocolDecl>(MD->getDeclContext()))
+    return false;
+  
+  Selector S = msg.getSelector();
+  
+  if (msg.isInstanceMessage()) {
+    // FIXME: Ideally we'd look at the receiver interface here, but that's not
+    // useful for init, because alloc returns 'id'. In theory, this could lead
+    // to false positives, for example if there existed a class that had an
+    // initWithObjects: implementation that does accept non-Objective-C pointer
+    // types, but the chance of that happening is pretty small compared to the
+    // gains that this analysis gives.
+    const ObjCInterfaceDecl *Class = MD->getClassInterface();
+
+    // -[NSArray initWithObjects:]
+    if (isReceiverClassOrSuperclass(Class, "NSArray") &&
+        S == initWithObjectsS)
+      return true;
+
+    // -[NSDictionary initWithObjectsAndKeys:]
+    if (isReceiverClassOrSuperclass(Class, "NSDictionary") &&
+        S == initWithObjectsAndKeysS)
+      return true;
+
+    // -[NSSet initWithObjects:]
+    if (isReceiverClassOrSuperclass(Class, "NSSet") &&
+        S == initWithObjectsS)
+      return true;
+
+    // -[NSOrderedSet initWithObjects:]
+    if (isReceiverClassOrSuperclass(Class, "NSOrderedSet") &&
+        S == initWithObjectsS)
+      return true;
+  } else {
+    const ObjCInterfaceDecl *Class = msg.getReceiverInterface();
+
+    // -[NSArray arrayWithObjects:]
+    if (isReceiverClassOrSuperclass(Class, "NSArray") &&
+        S == arrayWithObjectsS)
+      return true;
+
+    // -[NSDictionary dictionaryWithObjectsAndKeys:]
+    if (isReceiverClassOrSuperclass(Class, "NSDictionary") &&
+        S == dictionaryWithObjectsAndKeysS)
+      return true;
+
+    // -[NSSet setWithObjects:]
+    if (isReceiverClassOrSuperclass(Class, "NSSet") &&
+        S == setWithObjectsS)
+      return true;
+
+    // -[NSOrderedSet orderedSetWithObjects:]
+    if (isReceiverClassOrSuperclass(Class, "NSOrderedSet") &&
+        S == orderedSetWithObjectsS)
+      return true;
+  }
+
+  return false;
+}
+
+void VariadicMethodTypeChecker::checkPreObjCMessage(ObjCMessage msg,
+                                                    CheckerContext &C) const {
+  if (!BT) {
+    BT.reset(new APIMisuse("Arguments passed to variadic method aren't all "
+                           "Objective-C pointer types"));
+
+    ASTContext &Ctx = C.getASTContext();
+    arrayWithObjectsS = GetUnarySelector("arrayWithObjects", Ctx);
+    dictionaryWithObjectsAndKeysS = 
+      GetUnarySelector("dictionaryWithObjectsAndKeys", Ctx);
+    setWithObjectsS = GetUnarySelector("setWithObjects", Ctx);
+    orderedSetWithObjectsS = GetUnarySelector("orderedSetWithObjects", Ctx);
+
+    initWithObjectsS = GetUnarySelector("initWithObjects", Ctx);
+    initWithObjectsAndKeysS = GetUnarySelector("initWithObjectsAndKeys", Ctx);
+  }
+
+  if (!isVariadicMessage(msg))
+      return;
+
+  // We are not interested in the selector arguments since they have
+  // well-defined types, so the compiler will issue a warning for them.
+  unsigned variadicArgsBegin = msg.getSelector().getNumArgs();
+
+  // We're not interested in the last argument since it has to be nil or the
+  // compiler would have issued a warning for it elsewhere.
+  unsigned variadicArgsEnd = msg.getNumArgs() - 1;
+
+  if (variadicArgsEnd <= variadicArgsBegin)
+    return;
+
+  // Verify that all arguments have Objective-C types.
+  llvm::Optional<ExplodedNode*> errorNode;
+  ProgramStateRef state = C.getState();
+  
+  for (unsigned I = variadicArgsBegin; I != variadicArgsEnd; ++I) {
+    QualType ArgTy = msg.getArgType(I);
+    if (ArgTy->isObjCObjectPointerType())
+      continue;
+
+    // Block pointers are treaded as Objective-C pointers.
+    if (ArgTy->isBlockPointerType())
+      continue;
+
+    // Ignore pointer constants.
+    if (isa<loc::ConcreteInt>(msg.getArgSVal(I, C.getLocationContext(),
+                                             state)))
+      continue;
+    
+    // Ignore pointer types annotated with 'NSObject' attribute.
+    if (C.getASTContext().isObjCNSObjectType(ArgTy))
+      continue;
+    
+    // Ignore CF references, which can be toll-free bridged.
+    if (coreFoundation::isCFObjectRef(ArgTy))
+      continue;
+
+    // Generate only one error node to use for all bug reports.
+    if (!errorNode.hasValue()) {
+      errorNode = C.addTransition();
+    }
+
+    if (!errorNode.getValue())
+      continue;
+
+    SmallString<128> sbuf;
+    llvm::raw_svector_ostream os(sbuf);
+
+    if (const char *TypeName = GetReceiverNameType(msg))
+      os << "Argument to '" << TypeName << "' method '";
+    else
+      os << "Argument to method '";
+
+    os << msg.getSelector().getAsString() 
+      << "' should be an Objective-C pointer type, not '" 
+      << ArgTy.getAsString() << "'";
+
+    BugReport *R = new BugReport(*BT, os.str(),
+                                             errorNode.getValue());
+    R->addRange(msg.getArgSourceRange(I));
+    C.EmitReport(R);
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// Check registration.
+//===----------------------------------------------------------------------===//
+
+void ento::registerNilArgChecker(CheckerManager &mgr) {
+  mgr.registerChecker<NilArgChecker>();
+}
+
+void ento::registerCFNumberCreateChecker(CheckerManager &mgr) {
+  mgr.registerChecker<CFNumberCreateChecker>();
+}
+
+void ento::registerCFRetainReleaseChecker(CheckerManager &mgr) {
+  mgr.registerChecker<CFRetainReleaseChecker>();
+}
+
+void ento::registerClassReleaseChecker(CheckerManager &mgr) {
+  mgr.registerChecker<ClassReleaseChecker>();
+}
+
+void ento::registerVariadicMethodTypeChecker(CheckerManager &mgr) {
+  mgr.registerChecker<VariadicMethodTypeChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp
new file mode 100644
index 0000000..a4fc396
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp
@@ -0,0 +1,157 @@
+//== BoolAssignmentChecker.cpp - Boolean assignment 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 BoolAssignmentChecker, a builtin check in ExprEngine that
+// performs checks for assignment of non-Boolean values to Boolean variables.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+  class BoolAssignmentChecker : public Checker< check::Bind > {
+    mutable llvm::OwningPtr<BuiltinBug> BT;
+    void emitReport(ProgramStateRef state, CheckerContext &C) const;
+  public:
+    void checkBind(SVal loc, SVal val, const Stmt *S, CheckerContext &C) const;
+  };
+} // end anonymous namespace
+
+void BoolAssignmentChecker::emitReport(ProgramStateRef state,
+                                       CheckerContext &C) const {
+  if (ExplodedNode *N = C.addTransition(state)) {
+    if (!BT)
+      BT.reset(new BuiltinBug("Assignment of a non-Boolean value"));    
+    C.EmitReport(new BugReport(*BT, BT->getDescription(), N));
+  }
+}
+
+static bool isBooleanType(QualType Ty) {
+  if (Ty->isBooleanType()) // C++ or C99
+    return true;
+  
+  if (const TypedefType *TT = Ty->getAs<TypedefType>())
+    return TT->getDecl()->getName() == "BOOL"   || // Objective-C
+           TT->getDecl()->getName() == "_Bool"  || // stdbool.h < C99
+           TT->getDecl()->getName() == "Boolean";  // MacTypes.h
+  
+  return false;
+}
+
+void BoolAssignmentChecker::checkBind(SVal loc, SVal val, const Stmt *S,
+                                      CheckerContext &C) const {
+  
+  // We are only interested in stores into Booleans.
+  const TypedValueRegion *TR =
+    dyn_cast_or_null<TypedValueRegion>(loc.getAsRegion());
+  
+  if (!TR)
+    return;
+  
+  QualType valTy = TR->getValueType();
+  
+  if (!isBooleanType(valTy))
+    return;
+  
+  // Get the value of the right-hand side.  We only care about values
+  // that are defined (UnknownVals and UndefinedVals are handled by other
+  // checkers).
+  const DefinedSVal *DV = dyn_cast<DefinedSVal>(&val);
+  if (!DV)
+    return;
+    
+  // Check if the assigned value meets our criteria for correctness.  It must
+  // be a value that is either 0 or 1.  One way to check this is to see if
+  // the value is possibly < 0 (for a negative value) or greater than 1.
+  ProgramStateRef state = C.getState(); 
+  SValBuilder &svalBuilder = C.getSValBuilder();
+  ConstraintManager &CM = C.getConstraintManager();
+  
+  // First, ensure that the value is >= 0.  
+  DefinedSVal zeroVal = svalBuilder.makeIntVal(0, valTy);
+  SVal greaterThanOrEqualToZeroVal =
+    svalBuilder.evalBinOp(state, BO_GE, *DV, zeroVal,
+                          svalBuilder.getConditionType());
+  
+  DefinedSVal *greaterThanEqualToZero =
+    dyn_cast<DefinedSVal>(&greaterThanOrEqualToZeroVal);
+  
+  if (!greaterThanEqualToZero) {
+    // The SValBuilder cannot construct a valid SVal for this condition.
+    // This means we cannot properly reason about it.    
+    return;
+  }
+  
+  ProgramStateRef stateLT, stateGE;
+  llvm::tie(stateGE, stateLT) = CM.assumeDual(state, *greaterThanEqualToZero);
+  
+  // Is it possible for the value to be less than zero?
+  if (stateLT) {
+    // It is possible for the value to be less than zero.  We only
+    // want to emit a warning, however, if that value is fully constrained.
+    // If it it possible for the value to be >= 0, then essentially the
+    // value is underconstrained and there is nothing left to be done.
+    if (!stateGE)
+      emitReport(stateLT, C);
+    
+    // In either case, we are done.
+    return;
+  }
+  
+  // If we reach here, it must be the case that the value is constrained
+  // to only be >= 0.
+  assert(stateGE == state);
+  
+  // At this point we know that the value is >= 0.
+  // Now check to ensure that the value is <= 1.
+  DefinedSVal OneVal = svalBuilder.makeIntVal(1, valTy);
+  SVal lessThanEqToOneVal =
+    svalBuilder.evalBinOp(state, BO_LE, *DV, OneVal,
+                          svalBuilder.getConditionType());
+  
+  DefinedSVal *lessThanEqToOne =
+    dyn_cast<DefinedSVal>(&lessThanEqToOneVal);
+  
+  if (!lessThanEqToOne) {
+    // The SValBuilder cannot construct a valid SVal for this condition.
+    // This means we cannot properly reason about it.    
+    return;
+  }
+  
+  ProgramStateRef stateGT, stateLE;
+  llvm::tie(stateLE, stateGT) = CM.assumeDual(state, *lessThanEqToOne);
+  
+  // Is it possible for the value to be greater than one?
+  if (stateGT) {
+    // It is possible for the value to be greater than one.  We only
+    // want to emit a warning, however, if that value is fully constrained.
+    // If it is possible for the value to be <= 1, then essentially the
+    // value is underconstrained and there is nothing left to be done.
+    if (!stateLE)
+      emitReport(stateGT, C);
+    
+    // In either case, we are done.
+    return;
+  }
+  
+  // If we reach here, it must be the case that the value is constrained
+  // to only be <= 1.
+  assert(stateLE == state);
+}
+
+void ento::registerBoolAssignmentChecker(CheckerManager &mgr) {
+    mgr.registerChecker<BoolAssignmentChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
new file mode 100644
index 0000000..509bc79
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
@@ -0,0 +1,82 @@
+//=== BuiltinFunctionChecker.cpp --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This checker evaluates clang builtin functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/Basic/Builtins.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class BuiltinFunctionChecker : public Checker<eval::Call> {
+public:
+  bool evalCall(const CallExpr *CE, CheckerContext &C) const;
+};
+
+}
+
+bool BuiltinFunctionChecker::evalCall(const CallExpr *CE,
+                                      CheckerContext &C) const {
+  ProgramStateRef state = C.getState();
+  const FunctionDecl *FD = C.getCalleeDecl(CE);
+  const LocationContext *LCtx = C.getLocationContext();
+  if (!FD)
+    return false;
+
+  unsigned id = FD->getBuiltinID();
+
+  if (!id)
+    return false;
+
+  switch (id) {
+  case Builtin::BI__builtin_expect: {
+    // For __builtin_expect, just return the value of the subexpression.
+    assert (CE->arg_begin() != CE->arg_end());
+    SVal X = state->getSVal(*(CE->arg_begin()), LCtx);
+    C.addTransition(state->BindExpr(CE, LCtx, X));
+    return true;
+  }
+
+  case Builtin::BI__builtin_alloca: {
+    // FIXME: Refactor into StoreManager itself?
+    MemRegionManager& RM = C.getStoreManager().getRegionManager();
+    const AllocaRegion* R =
+      RM.getAllocaRegion(CE, C.getCurrentBlockCount(), C.getLocationContext());
+
+    // Set the extent of the region in bytes. This enables us to use the
+    // SVal of the argument directly. If we save the extent in bits, we
+    // cannot represent values like symbol*8.
+    DefinedOrUnknownSVal Size =
+      cast<DefinedOrUnknownSVal>(state->getSVal(*(CE->arg_begin()), LCtx));
+
+    SValBuilder& svalBuilder = C.getSValBuilder();
+    DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder);
+    DefinedOrUnknownSVal extentMatchesSizeArg =
+      svalBuilder.evalEQ(state, Extent, Size);
+    state = state->assume(extentMatchesSizeArg, true);
+
+    C.addTransition(state->BindExpr(CE, LCtx, loc::MemRegionVal(R)));
+    return true;
+  }
+  }
+
+  return false;
+}
+
+void ento::registerBuiltinFunctionChecker(CheckerManager &mgr) {
+  mgr.registerChecker<BuiltinFunctionChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
new file mode 100644
index 0000000..75d5448
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -0,0 +1,81 @@
+clang_tablegen(Checkers.inc -gen-clang-sa-checkers
+  -I ${CMAKE_CURRENT_SOURCE_DIR}/../../../include
+  SOURCE Checkers.td
+  TARGET ClangSACheckers)
+
+set(LLVM_USED_LIBS clangBasic clangAST clangStaticAnalyzerCore)
+
+add_clang_library(clangStaticAnalyzerCheckers
+  AdjustedReturnValueChecker.cpp
+  AnalyzerStatsChecker.cpp
+  ArrayBoundChecker.cpp
+  ArrayBoundCheckerV2.cpp
+  AttrNonNullChecker.cpp
+  BasicObjCFoundationChecks.cpp
+  BoolAssignmentChecker.cpp
+  BuiltinFunctionChecker.cpp
+  CStringChecker.cpp
+  CStringSyntaxChecker.cpp
+  CallAndMessageChecker.cpp
+  CastSizeChecker.cpp
+  CastToStructChecker.cpp
+  CheckObjCDealloc.cpp
+  CheckObjCInstMethSignature.cpp
+  CheckSecuritySyntaxOnly.cpp
+  CheckSizeofPointer.cpp
+  CheckerDocumentation.cpp
+  ChrootChecker.cpp
+  ClangCheckers.cpp
+  CommonBugCategories.cpp
+  DeadStoresChecker.cpp
+  DebugCheckers.cpp
+  DereferenceChecker.cpp
+  DivZeroChecker.cpp
+  FixedAddressChecker.cpp
+  GenericTaintChecker.cpp
+  IdempotentOperationChecker.cpp
+  IteratorsChecker.cpp
+  IntervalTest.cpp
+  LLVMConventionsChecker.cpp
+  MacOSKeychainAPIChecker.cpp
+  MacOSXAPIChecker.cpp
+  MallocChecker.cpp
+  MallocOverflowSecurityChecker.cpp
+  MallocSizeofChecker.cpp
+  NSAutoreleasePoolChecker.cpp
+  NSErrorChecker.cpp
+  NoReturnFunctionChecker.cpp
+  OSAtomicChecker.cpp
+  ObjCAtSyncChecker.cpp
+  ObjCContainersASTChecker.cpp
+  ObjCContainersChecker.cpp
+  ObjCSelfInitChecker.cpp
+  ObjCUnusedIVarsChecker.cpp
+  PointerArithChecker.cpp
+  PointerSubChecker.cpp
+  PthreadLockChecker.cpp
+  RetainCountChecker.cpp
+  ReturnPointerRangeChecker.cpp
+  ReturnUndefChecker.cpp
+  StackAddrEscapeChecker.cpp
+  StreamChecker.cpp
+  TaintTesterChecker.cpp
+  UndefBranchChecker.cpp
+  UndefCapturedBlockVarChecker.cpp
+  UndefResultChecker.cpp
+  UndefinedArraySubscriptChecker.cpp
+  UndefinedAssignmentChecker.cpp
+  UnixAPIChecker.cpp
+  UnreachableCodeChecker.cpp
+  VLASizeChecker.cpp
+  VirtualCallChecker.cpp
+  )
+
+add_dependencies(clangStaticAnalyzerCheckers
+  clangStaticAnalyzerCore
+  ClangAttrClasses
+  ClangAttrList
+  ClangDeclNodes
+  ClangStmtNodes
+  ClangSACheckers
+  )
diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
new file mode 100644
index 0000000..9eb7edf
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -0,0 +1,1981 @@
+//= CStringChecker.cpp - Checks calls to C string functions --------*- C++ -*-//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines CStringChecker, which is an assortment of checks on calls
+// to functions in <string.h>.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "InterCheckerAPI.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class CStringChecker : public Checker< eval::Call,
+                                         check::PreStmt<DeclStmt>,
+                                         check::LiveSymbols,
+                                         check::DeadSymbols,
+                                         check::RegionChanges
+                                         > {
+  mutable OwningPtr<BugType> BT_Null,
+                             BT_Bounds,
+                             BT_Overlap,
+                             BT_NotCString,
+                             BT_AdditionOverflow;
+
+  mutable const char *CurrentFunctionDescription;
+
+public:
+  /// The filter is used to filter out the diagnostics which are not enabled by
+  /// the user.
+  struct CStringChecksFilter {
+    DefaultBool CheckCStringNullArg;
+    DefaultBool CheckCStringOutOfBounds;
+    DefaultBool CheckCStringBufferOverlap;
+    DefaultBool CheckCStringNotNullTerm;
+  };
+
+  CStringChecksFilter Filter;
+
+  static void *getTag() { static int tag; return &tag; }
+
+  bool evalCall(const CallExpr *CE, CheckerContext &C) const;
+  void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const;
+  void checkLiveSymbols(ProgramStateRef state, SymbolReaper &SR) const;
+  void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
+  bool wantsRegionChangeUpdate(ProgramStateRef state) const;
+
+  ProgramStateRef 
+    checkRegionChanges(ProgramStateRef state,
+                       const StoreManager::InvalidatedSymbols *,
+                       ArrayRef<const MemRegion *> ExplicitRegions,
+                       ArrayRef<const MemRegion *> Regions,
+                       const CallOrObjCMessage *Call) const;
+
+  typedef void (CStringChecker::*FnCheck)(CheckerContext &,
+                                          const CallExpr *) const;
+
+  void evalMemcpy(CheckerContext &C, const CallExpr *CE) const;
+  void evalMempcpy(CheckerContext &C, const CallExpr *CE) const;
+  void evalMemmove(CheckerContext &C, const CallExpr *CE) const;
+  void evalBcopy(CheckerContext &C, const CallExpr *CE) const;
+  void evalCopyCommon(CheckerContext &C, const CallExpr *CE,
+                      ProgramStateRef state,
+                      const Expr *Size,
+                      const Expr *Source,
+                      const Expr *Dest,
+                      bool Restricted = false,
+                      bool IsMempcpy = false) const;
+
+  void evalMemcmp(CheckerContext &C, const CallExpr *CE) const;
+
+  void evalstrLength(CheckerContext &C, const CallExpr *CE) const;
+  void evalstrnLength(CheckerContext &C, const CallExpr *CE) const;
+  void evalstrLengthCommon(CheckerContext &C,
+                           const CallExpr *CE, 
+                           bool IsStrnlen = false) const;
+
+  void evalStrcpy(CheckerContext &C, const CallExpr *CE) const;
+  void evalStrncpy(CheckerContext &C, const CallExpr *CE) const;
+  void evalStpcpy(CheckerContext &C, const CallExpr *CE) const;
+  void evalStrcpyCommon(CheckerContext &C,
+                        const CallExpr *CE,
+                        bool returnEnd,
+                        bool isBounded,
+                        bool isAppending) const;
+
+  void evalStrcat(CheckerContext &C, const CallExpr *CE) const;
+  void evalStrncat(CheckerContext &C, const CallExpr *CE) const;
+
+  void evalStrcmp(CheckerContext &C, const CallExpr *CE) const;
+  void evalStrncmp(CheckerContext &C, const CallExpr *CE) const;
+  void evalStrcasecmp(CheckerContext &C, const CallExpr *CE) const;
+  void evalStrncasecmp(CheckerContext &C, const CallExpr *CE) const;
+  void evalStrcmpCommon(CheckerContext &C,
+                        const CallExpr *CE,
+                        bool isBounded = false,
+                        bool ignoreCase = false) const;
+
+  // Utility methods
+  std::pair<ProgramStateRef , ProgramStateRef >
+  static assumeZero(CheckerContext &C,
+                    ProgramStateRef state, SVal V, QualType Ty);
+
+  static ProgramStateRef setCStringLength(ProgramStateRef state,
+                                              const MemRegion *MR,
+                                              SVal strLength);
+  static SVal getCStringLengthForRegion(CheckerContext &C,
+                                        ProgramStateRef &state,
+                                        const Expr *Ex,
+                                        const MemRegion *MR,
+                                        bool hypothetical);
+  SVal getCStringLength(CheckerContext &C,
+                        ProgramStateRef &state,
+                        const Expr *Ex,
+                        SVal Buf,
+                        bool hypothetical = false) const;
+
+  const StringLiteral *getCStringLiteral(CheckerContext &C, 
+                                         ProgramStateRef &state,
+                                         const Expr *expr,  
+                                         SVal val) const;
+
+  static ProgramStateRef InvalidateBuffer(CheckerContext &C,
+                                              ProgramStateRef state,
+                                              const Expr *Ex, SVal V);
+
+  static bool SummarizeRegion(raw_ostream &os, ASTContext &Ctx,
+                              const MemRegion *MR);
+
+  // Re-usable checks
+  ProgramStateRef checkNonNull(CheckerContext &C,
+                                   ProgramStateRef state,
+                                   const Expr *S,
+                                   SVal l) const;
+  ProgramStateRef CheckLocation(CheckerContext &C,
+                                    ProgramStateRef state,
+                                    const Expr *S,
+                                    SVal l,
+                                    const char *message = NULL) const;
+  ProgramStateRef CheckBufferAccess(CheckerContext &C,
+                                        ProgramStateRef state,
+                                        const Expr *Size,
+                                        const Expr *FirstBuf,
+                                        const Expr *SecondBuf,
+                                        const char *firstMessage = NULL,
+                                        const char *secondMessage = NULL,
+                                        bool WarnAboutSize = false) const;
+
+  ProgramStateRef CheckBufferAccess(CheckerContext &C,
+                                        ProgramStateRef state,
+                                        const Expr *Size,
+                                        const Expr *Buf,
+                                        const char *message = NULL,
+                                        bool WarnAboutSize = false) const {
+    // This is a convenience override.
+    return CheckBufferAccess(C, state, Size, Buf, NULL, message, NULL,
+                             WarnAboutSize);
+  }
+  ProgramStateRef CheckOverlap(CheckerContext &C,
+                                   ProgramStateRef state,
+                                   const Expr *Size,
+                                   const Expr *First,
+                                   const Expr *Second) const;
+  void emitOverlapBug(CheckerContext &C,
+                      ProgramStateRef state,
+                      const Stmt *First,
+                      const Stmt *Second) const;
+
+  ProgramStateRef checkAdditionOverflow(CheckerContext &C,
+                                            ProgramStateRef state,
+                                            NonLoc left,
+                                            NonLoc right) const;
+};
+
+class CStringLength {
+public:
+  typedef llvm::ImmutableMap<const MemRegion *, SVal> EntryMap;
+};
+} //end anonymous namespace
+
+namespace clang {
+namespace ento {
+  template <>
+  struct ProgramStateTrait<CStringLength> 
+    : public ProgramStatePartialTrait<CStringLength::EntryMap> {
+    static void *GDMIndex() { return CStringChecker::getTag(); }
+  };
+}
+}
+
+//===----------------------------------------------------------------------===//
+// Individual checks and utility methods.
+//===----------------------------------------------------------------------===//
+
+std::pair<ProgramStateRef , ProgramStateRef >
+CStringChecker::assumeZero(CheckerContext &C, ProgramStateRef state, SVal V,
+                           QualType Ty) {
+  DefinedSVal *val = dyn_cast<DefinedSVal>(&V);
+  if (!val)
+    return std::pair<ProgramStateRef , ProgramStateRef >(state, state);
+
+  SValBuilder &svalBuilder = C.getSValBuilder();
+  DefinedOrUnknownSVal zero = svalBuilder.makeZeroVal(Ty);
+  return state->assume(svalBuilder.evalEQ(state, *val, zero));
+}
+
+ProgramStateRef CStringChecker::checkNonNull(CheckerContext &C,
+                                            ProgramStateRef state,
+                                            const Expr *S, SVal l) const {
+  // If a previous check has failed, propagate the failure.
+  if (!state)
+    return NULL;
+
+  ProgramStateRef stateNull, stateNonNull;
+  llvm::tie(stateNull, stateNonNull) = assumeZero(C, state, l, S->getType());
+
+  if (stateNull && !stateNonNull) {
+    if (!Filter.CheckCStringNullArg)
+      return NULL;
+
+    ExplodedNode *N = C.generateSink(stateNull);
+    if (!N)
+      return NULL;
+
+    if (!BT_Null)
+      BT_Null.reset(new BuiltinBug("Unix API",
+        "Null pointer argument in call to byte string function"));
+
+    SmallString<80> buf;
+    llvm::raw_svector_ostream os(buf);
+    assert(CurrentFunctionDescription);
+    os << "Null pointer argument in call to " << CurrentFunctionDescription;
+
+    // Generate a report for this bug.
+    BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Null.get());
+    BugReport *report = new BugReport(*BT, os.str(), N);
+
+    report->addRange(S->getSourceRange());
+    report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, S,
+                                                                    report));
+    C.EmitReport(report);
+    return NULL;
+  }
+
+  // From here on, assume that the value is non-null.
+  assert(stateNonNull);
+  return stateNonNull;
+}
+
+// FIXME: This was originally copied from ArrayBoundChecker.cpp. Refactor?
+ProgramStateRef CStringChecker::CheckLocation(CheckerContext &C,
+                                             ProgramStateRef state,
+                                             const Expr *S, SVal l,
+                                             const char *warningMsg) const {
+  // If a previous check has failed, propagate the failure.
+  if (!state)
+    return NULL;
+
+  // Check for out of bound array element access.
+  const MemRegion *R = l.getAsRegion();
+  if (!R)
+    return state;
+
+  const ElementRegion *ER = dyn_cast<ElementRegion>(R);
+  if (!ER)
+    return state;
+
+  assert(ER->getValueType() == C.getASTContext().CharTy &&
+    "CheckLocation should only be called with char* ElementRegions");
+
+  // Get the size of the array.
+  const SubRegion *superReg = cast<SubRegion>(ER->getSuperRegion());
+  SValBuilder &svalBuilder = C.getSValBuilder();
+  SVal Extent = 
+    svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder));
+  DefinedOrUnknownSVal Size = cast<DefinedOrUnknownSVal>(Extent);
+
+  // Get the index of the accessed element.
+  DefinedOrUnknownSVal Idx = cast<DefinedOrUnknownSVal>(ER->getIndex());
+
+  ProgramStateRef StInBound = state->assumeInBound(Idx, Size, true);
+  ProgramStateRef StOutBound = state->assumeInBound(Idx, Size, false);
+  if (StOutBound && !StInBound) {
+    ExplodedNode *N = C.generateSink(StOutBound);
+    if (!N)
+      return NULL;
+
+    if (!BT_Bounds) {
+      BT_Bounds.reset(new BuiltinBug("Out-of-bound array access",
+        "Byte string function accesses out-of-bound array element"));
+    }
+    BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Bounds.get());
+
+    // Generate a report for this bug.
+    BugReport *report;
+    if (warningMsg) {
+      report = new BugReport(*BT, warningMsg, N);
+    } else {
+      assert(CurrentFunctionDescription);
+      assert(CurrentFunctionDescription[0] != '\0');
+
+      SmallString<80> buf;
+      llvm::raw_svector_ostream os(buf);
+      os << (char)toupper(CurrentFunctionDescription[0])
+         << &CurrentFunctionDescription[1]
+         << " accesses out-of-bound array element";
+      report = new BugReport(*BT, os.str(), N);      
+    }
+
+    // FIXME: It would be nice to eventually make this diagnostic more clear,
+    // e.g., by referencing the original declaration or by saying *why* this
+    // reference is outside the range.
+
+    report->addRange(S->getSourceRange());
+    C.EmitReport(report);
+    return NULL;
+  }
+  
+  // Array bound check succeeded.  From this point forward the array bound
+  // should always succeed.
+  return StInBound;
+}
+
+ProgramStateRef CStringChecker::CheckBufferAccess(CheckerContext &C,
+                                                 ProgramStateRef state,
+                                                 const Expr *Size,
+                                                 const Expr *FirstBuf,
+                                                 const Expr *SecondBuf,
+                                                 const char *firstMessage,
+                                                 const char *secondMessage,
+                                                 bool WarnAboutSize) const {
+  // If a previous check has failed, propagate the failure.
+  if (!state)
+    return NULL;
+
+  SValBuilder &svalBuilder = C.getSValBuilder();
+  ASTContext &Ctx = svalBuilder.getContext();
+  const LocationContext *LCtx = C.getLocationContext();
+
+  QualType sizeTy = Size->getType();
+  QualType PtrTy = Ctx.getPointerType(Ctx.CharTy);
+
+  // Check that the first buffer is non-null.
+  SVal BufVal = state->getSVal(FirstBuf, LCtx);
+  state = checkNonNull(C, state, FirstBuf, BufVal);
+  if (!state)
+    return NULL;
+
+  // If out-of-bounds checking is turned off, skip the rest.
+  if (!Filter.CheckCStringOutOfBounds)
+    return state;
+
+  // Get the access length and make sure it is known.
+  // FIXME: This assumes the caller has already checked that the access length
+  // is positive. And that it's unsigned.
+  SVal LengthVal = state->getSVal(Size, LCtx);
+  NonLoc *Length = dyn_cast<NonLoc>(&LengthVal);
+  if (!Length)
+    return state;
+
+  // Compute the offset of the last element to be accessed: size-1.
+  NonLoc One = cast<NonLoc>(svalBuilder.makeIntVal(1, sizeTy));
+  NonLoc LastOffset = cast<NonLoc>(svalBuilder.evalBinOpNN(state, BO_Sub,
+                                                    *Length, One, sizeTy));
+
+  // Check that the first buffer is sufficiently long.
+  SVal BufStart = svalBuilder.evalCast(BufVal, PtrTy, FirstBuf->getType());
+  if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) {
+    const Expr *warningExpr = (WarnAboutSize ? Size : FirstBuf);
+
+    SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc,
+                                          LastOffset, PtrTy);
+    state = CheckLocation(C, state, warningExpr, BufEnd, firstMessage);
+
+    // If the buffer isn't large enough, abort.
+    if (!state)
+      return NULL;
+  }
+
+  // If there's a second buffer, check it as well.
+  if (SecondBuf) {
+    BufVal = state->getSVal(SecondBuf, LCtx);
+    state = checkNonNull(C, state, SecondBuf, BufVal);
+    if (!state)
+      return NULL;
+
+    BufStart = svalBuilder.evalCast(BufVal, PtrTy, SecondBuf->getType());
+    if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) {
+      const Expr *warningExpr = (WarnAboutSize ? Size : SecondBuf);
+
+      SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc,
+                                            LastOffset, PtrTy);
+      state = CheckLocation(C, state, warningExpr, BufEnd, secondMessage);
+    }
+  }
+
+  // Large enough or not, return this state!
+  return state;
+}
+
+ProgramStateRef CStringChecker::CheckOverlap(CheckerContext &C,
+                                            ProgramStateRef state,
+                                            const Expr *Size,
+                                            const Expr *First,
+                                            const Expr *Second) const {
+  if (!Filter.CheckCStringBufferOverlap)
+    return state;
+
+  // Do a simple check for overlap: if the two arguments are from the same
+  // buffer, see if the end of the first is greater than the start of the second
+  // or vice versa.
+
+  // If a previous check has failed, propagate the failure.
+  if (!state)
+    return NULL;
+
+  ProgramStateRef stateTrue, stateFalse;
+
+  // Get the buffer values and make sure they're known locations.
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal firstVal = state->getSVal(First, LCtx);
+  SVal secondVal = state->getSVal(Second, LCtx);
+
+  Loc *firstLoc = dyn_cast<Loc>(&firstVal);
+  if (!firstLoc)
+    return state;
+
+  Loc *secondLoc = dyn_cast<Loc>(&secondVal);
+  if (!secondLoc)
+    return state;
+
+  // Are the two values the same?
+  SValBuilder &svalBuilder = C.getSValBuilder();  
+  llvm::tie(stateTrue, stateFalse) =
+    state->assume(svalBuilder.evalEQ(state, *firstLoc, *secondLoc));
+
+  if (stateTrue && !stateFalse) {
+    // If the values are known to be equal, that's automatically an overlap.
+    emitOverlapBug(C, stateTrue, First, Second);
+    return NULL;
+  }
+
+  // assume the two expressions are not equal.
+  assert(stateFalse);
+  state = stateFalse;
+
+  // Which value comes first?
+  QualType cmpTy = svalBuilder.getConditionType();
+  SVal reverse = svalBuilder.evalBinOpLL(state, BO_GT,
+                                         *firstLoc, *secondLoc, cmpTy);
+  DefinedOrUnknownSVal *reverseTest = dyn_cast<DefinedOrUnknownSVal>(&reverse);
+  if (!reverseTest)
+    return state;
+
+  llvm::tie(stateTrue, stateFalse) = state->assume(*reverseTest);
+  if (stateTrue) {
+    if (stateFalse) {
+      // If we don't know which one comes first, we can't perform this test.
+      return state;
+    } else {
+      // Switch the values so that firstVal is before secondVal.
+      Loc *tmpLoc = firstLoc;
+      firstLoc = secondLoc;
+      secondLoc = tmpLoc;
+
+      // Switch the Exprs as well, so that they still correspond.
+      const Expr *tmpExpr = First;
+      First = Second;
+      Second = tmpExpr;
+    }
+  }
+
+  // Get the length, and make sure it too is known.
+  SVal LengthVal = state->getSVal(Size, LCtx);
+  NonLoc *Length = dyn_cast<NonLoc>(&LengthVal);
+  if (!Length)
+    return state;
+
+  // Convert the first buffer's start address to char*.
+  // Bail out if the cast fails.
+  ASTContext &Ctx = svalBuilder.getContext();
+  QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy);
+  SVal FirstStart = svalBuilder.evalCast(*firstLoc, CharPtrTy, 
+                                         First->getType());
+  Loc *FirstStartLoc = dyn_cast<Loc>(&FirstStart);
+  if (!FirstStartLoc)
+    return state;
+
+  // Compute the end of the first buffer. Bail out if THAT fails.
+  SVal FirstEnd = svalBuilder.evalBinOpLN(state, BO_Add,
+                                 *FirstStartLoc, *Length, CharPtrTy);
+  Loc *FirstEndLoc = dyn_cast<Loc>(&FirstEnd);
+  if (!FirstEndLoc)
+    return state;
+
+  // Is the end of the first buffer past the start of the second buffer?
+  SVal Overlap = svalBuilder.evalBinOpLL(state, BO_GT,
+                                *FirstEndLoc, *secondLoc, cmpTy);
+  DefinedOrUnknownSVal *OverlapTest = dyn_cast<DefinedOrUnknownSVal>(&Overlap);
+  if (!OverlapTest)
+    return state;
+
+  llvm::tie(stateTrue, stateFalse) = state->assume(*OverlapTest);
+
+  if (stateTrue && !stateFalse) {
+    // Overlap!
+    emitOverlapBug(C, stateTrue, First, Second);
+    return NULL;
+  }
+
+  // assume the two expressions don't overlap.
+  assert(stateFalse);
+  return stateFalse;
+}
+
+void CStringChecker::emitOverlapBug(CheckerContext &C, ProgramStateRef state,
+                                  const Stmt *First, const Stmt *Second) const {
+  ExplodedNode *N = C.generateSink(state);
+  if (!N)
+    return;
+
+  if (!BT_Overlap)
+    BT_Overlap.reset(new BugType("Unix API", "Improper arguments"));
+
+  // Generate a report for this bug.
+  BugReport *report = 
+    new BugReport(*BT_Overlap,
+      "Arguments must not be overlapping buffers", N);
+  report->addRange(First->getSourceRange());
+  report->addRange(Second->getSourceRange());
+
+  C.EmitReport(report);
+}
+
+ProgramStateRef CStringChecker::checkAdditionOverflow(CheckerContext &C,
+                                                     ProgramStateRef state,
+                                                     NonLoc left,
+                                                     NonLoc right) const {
+  // If out-of-bounds checking is turned off, skip the rest.
+  if (!Filter.CheckCStringOutOfBounds)
+    return state;
+
+  // If a previous check has failed, propagate the failure.
+  if (!state)
+    return NULL;
+
+  SValBuilder &svalBuilder = C.getSValBuilder();
+  BasicValueFactory &BVF = svalBuilder.getBasicValueFactory();
+
+  QualType sizeTy = svalBuilder.getContext().getSizeType();
+  const llvm::APSInt &maxValInt = BVF.getMaxValue(sizeTy);
+  NonLoc maxVal = svalBuilder.makeIntVal(maxValInt);
+
+  SVal maxMinusRight;
+  if (isa<nonloc::ConcreteInt>(right)) {
+    maxMinusRight = svalBuilder.evalBinOpNN(state, BO_Sub, maxVal, right,
+                                                 sizeTy);
+  } else {
+    // Try switching the operands. (The order of these two assignments is
+    // important!)
+    maxMinusRight = svalBuilder.evalBinOpNN(state, BO_Sub, maxVal, left, 
+                                            sizeTy);
+    left = right;
+  }
+
+  if (NonLoc *maxMinusRightNL = dyn_cast<NonLoc>(&maxMinusRight)) {
+    QualType cmpTy = svalBuilder.getConditionType();
+    // If left > max - right, we have an overflow.
+    SVal willOverflow = svalBuilder.evalBinOpNN(state, BO_GT, left,
+                                                *maxMinusRightNL, cmpTy);
+
+    ProgramStateRef stateOverflow, stateOkay;
+    llvm::tie(stateOverflow, stateOkay) =
+      state->assume(cast<DefinedOrUnknownSVal>(willOverflow));
+
+    if (stateOverflow && !stateOkay) {
+      // We have an overflow. Emit a bug report.
+      ExplodedNode *N = C.generateSink(stateOverflow);
+      if (!N)
+        return NULL;
+
+      if (!BT_AdditionOverflow)
+        BT_AdditionOverflow.reset(new BuiltinBug("API",
+          "Sum of expressions causes overflow"));
+
+      // This isn't a great error message, but this should never occur in real
+      // code anyway -- you'd have to create a buffer longer than a size_t can
+      // represent, which is sort of a contradiction.
+      const char *warning =
+        "This expression will create a string whose length is too big to "
+        "be represented as a size_t";
+
+      // Generate a report for this bug.
+      BugReport *report = new BugReport(*BT_AdditionOverflow, warning, N);
+      C.EmitReport(report);        
+
+      return NULL;
+    }
+
+    // From now on, assume an overflow didn't occur.
+    assert(stateOkay);
+    state = stateOkay;
+  }
+
+  return state;
+}
+
+ProgramStateRef CStringChecker::setCStringLength(ProgramStateRef state,
+                                                const MemRegion *MR,
+                                                SVal strLength) {
+  assert(!strLength.isUndef() && "Attempt to set an undefined string length");
+
+  MR = MR->StripCasts();
+
+  switch (MR->getKind()) {
+  case MemRegion::StringRegionKind:
+    // FIXME: This can happen if we strcpy() into a string region. This is
+    // undefined [C99 6.4.5p6], but we should still warn about it.
+    return state;
+
+  case MemRegion::SymbolicRegionKind:
+  case MemRegion::AllocaRegionKind:
+  case MemRegion::VarRegionKind:
+  case MemRegion::FieldRegionKind:
+  case MemRegion::ObjCIvarRegionKind:
+    // These are the types we can currently track string lengths for.
+    break;
+
+  case MemRegion::ElementRegionKind:
+    // FIXME: Handle element regions by upper-bounding the parent region's
+    // string length.
+    return state;
+
+  default:
+    // Other regions (mostly non-data) can't have a reliable C string length.
+    // For now, just ignore the change.
+    // FIXME: These are rare but not impossible. We should output some kind of
+    // warning for things like strcpy((char[]){'a', 0}, "b");
+    return state;
+  }
+
+  if (strLength.isUnknown())
+    return state->remove<CStringLength>(MR);
+
+  return state->set<CStringLength>(MR, strLength);
+}
+
+SVal CStringChecker::getCStringLengthForRegion(CheckerContext &C,
+                                               ProgramStateRef &state,
+                                               const Expr *Ex,
+                                               const MemRegion *MR,
+                                               bool hypothetical) {
+  if (!hypothetical) {
+    // If there's a recorded length, go ahead and return it.
+    const SVal *Recorded = state->get<CStringLength>(MR);
+    if (Recorded)
+      return *Recorded;
+  }
+  
+  // Otherwise, get a new symbol and update the state.
+  unsigned Count = C.getCurrentBlockCount();
+  SValBuilder &svalBuilder = C.getSValBuilder();
+  QualType sizeTy = svalBuilder.getContext().getSizeType();
+  SVal strLength = svalBuilder.getMetadataSymbolVal(CStringChecker::getTag(),
+                                                    MR, Ex, sizeTy, Count);
+
+  if (!hypothetical)
+    state = state->set<CStringLength>(MR, strLength);
+
+  return strLength;
+}
+
+SVal CStringChecker::getCStringLength(CheckerContext &C, ProgramStateRef &state,
+                                      const Expr *Ex, SVal Buf,
+                                      bool hypothetical) const {
+  const MemRegion *MR = Buf.getAsRegion();
+  if (!MR) {
+    // If we can't get a region, see if it's something we /know/ isn't a
+    // C string. In the context of locations, the only time we can issue such
+    // a warning is for labels.
+    if (loc::GotoLabel *Label = dyn_cast<loc::GotoLabel>(&Buf)) {
+      if (!Filter.CheckCStringNotNullTerm)
+        return UndefinedVal();
+
+      if (ExplodedNode *N = C.addTransition(state)) {
+        if (!BT_NotCString)
+          BT_NotCString.reset(new BuiltinBug("Unix API",
+            "Argument is not a null-terminated string."));
+
+        SmallString<120> buf;
+        llvm::raw_svector_ostream os(buf);
+        assert(CurrentFunctionDescription);
+        os << "Argument to " << CurrentFunctionDescription
+           << " is the address of the label '" << Label->getLabel()->getName()
+           << "', which is not a null-terminated string";
+
+        // Generate a report for this bug.
+        BugReport *report = new BugReport(*BT_NotCString,
+                                                          os.str(), N);
+
+        report->addRange(Ex->getSourceRange());
+        C.EmitReport(report);        
+      }
+      return UndefinedVal();
+
+    }
+
+    // If it's not a region and not a label, give up.
+    return UnknownVal();
+  }
+
+  // If we have a region, strip casts from it and see if we can figure out
+  // its length. For anything we can't figure out, just return UnknownVal.
+  MR = MR->StripCasts();
+
+  switch (MR->getKind()) {
+  case MemRegion::StringRegionKind: {
+    // Modifying the contents of string regions is undefined [C99 6.4.5p6],
+    // so we can assume that the byte length is the correct C string length.
+    SValBuilder &svalBuilder = C.getSValBuilder();
+    QualType sizeTy = svalBuilder.getContext().getSizeType();
+    const StringLiteral *strLit = cast<StringRegion>(MR)->getStringLiteral();
+    return svalBuilder.makeIntVal(strLit->getByteLength(), sizeTy);
+  }
+  case MemRegion::SymbolicRegionKind:
+  case MemRegion::AllocaRegionKind:
+  case MemRegion::VarRegionKind:
+  case MemRegion::FieldRegionKind:
+  case MemRegion::ObjCIvarRegionKind:
+    return getCStringLengthForRegion(C, state, Ex, MR, hypothetical);
+  case MemRegion::CompoundLiteralRegionKind:
+    // FIXME: Can we track this? Is it necessary?
+    return UnknownVal();
+  case MemRegion::ElementRegionKind:
+    // FIXME: How can we handle this? It's not good enough to subtract the
+    // offset from the base string length; consider "123\x00567" and &a[5].
+    return UnknownVal();
+  default:
+    // Other regions (mostly non-data) can't have a reliable C string length.
+    // In this case, an error is emitted and UndefinedVal is returned.
+    // The caller should always be prepared to handle this case.
+    if (!Filter.CheckCStringNotNullTerm)
+      return UndefinedVal();
+
+    if (ExplodedNode *N = C.addTransition(state)) {
+      if (!BT_NotCString)
+        BT_NotCString.reset(new BuiltinBug("Unix API",
+          "Argument is not a null-terminated string."));
+
+      SmallString<120> buf;
+      llvm::raw_svector_ostream os(buf);
+
+      assert(CurrentFunctionDescription);
+      os << "Argument to " << CurrentFunctionDescription << " is ";
+
+      if (SummarizeRegion(os, C.getASTContext(), MR))
+        os << ", which is not a null-terminated string";
+      else
+        os << "not a null-terminated string";
+
+      // Generate a report for this bug.
+      BugReport *report = new BugReport(*BT_NotCString,
+                                                        os.str(), N);
+
+      report->addRange(Ex->getSourceRange());
+      C.EmitReport(report);        
+    }
+
+    return UndefinedVal();
+  }
+}
+
+const StringLiteral *CStringChecker::getCStringLiteral(CheckerContext &C,
+  ProgramStateRef &state, const Expr *expr, SVal val) const {
+
+  // Get the memory region pointed to by the val.
+  const MemRegion *bufRegion = val.getAsRegion();
+  if (!bufRegion)
+    return NULL; 
+
+  // Strip casts off the memory region.
+  bufRegion = bufRegion->StripCasts();
+
+  // Cast the memory region to a string region.
+  const StringRegion *strRegion= dyn_cast<StringRegion>(bufRegion);
+  if (!strRegion)
+    return NULL; 
+
+  // Return the actual string in the string region.
+  return strRegion->getStringLiteral();
+}
+
+ProgramStateRef CStringChecker::InvalidateBuffer(CheckerContext &C,
+                                                ProgramStateRef state,
+                                                const Expr *E, SVal V) {
+  Loc *L = dyn_cast<Loc>(&V);
+  if (!L)
+    return state;
+
+  // FIXME: This is a simplified version of what's in CFRefCount.cpp -- it makes
+  // some assumptions about the value that CFRefCount can't. Even so, it should
+  // probably be refactored.
+  if (loc::MemRegionVal* MR = dyn_cast<loc::MemRegionVal>(L)) {
+    const MemRegion *R = MR->getRegion()->StripCasts();
+
+    // Are we dealing with an ElementRegion?  If so, we should be invalidating
+    // the super-region.
+    if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
+      R = ER->getSuperRegion();
+      // FIXME: What about layers of ElementRegions?
+    }
+
+    // Invalidate this region.
+    unsigned Count = C.getCurrentBlockCount();
+    const LocationContext *LCtx = C.getPredecessor()->getLocationContext();
+    return state->invalidateRegions(R, E, Count, LCtx);
+  }
+
+  // If we have a non-region value by chance, just remove the binding.
+  // FIXME: is this necessary or correct? This handles the non-Region
+  //  cases.  Is it ever valid to store to these?
+  return state->unbindLoc(*L);
+}
+
+bool CStringChecker::SummarizeRegion(raw_ostream &os, ASTContext &Ctx,
+                                     const MemRegion *MR) {
+  const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(MR);
+
+  switch (MR->getKind()) {
+  case MemRegion::FunctionTextRegionKind: {
+    const FunctionDecl *FD = cast<FunctionTextRegion>(MR)->getDecl();
+    if (FD)
+      os << "the address of the function '" << *FD << '\'';
+    else
+      os << "the address of a function";
+    return true;
+  }
+  case MemRegion::BlockTextRegionKind:
+    os << "block text";
+    return true;
+  case MemRegion::BlockDataRegionKind:
+    os << "a block";
+    return true;
+  case MemRegion::CXXThisRegionKind:
+  case MemRegion::CXXTempObjectRegionKind:
+    os << "a C++ temp object of type " << TVR->getValueType().getAsString();
+    return true;
+  case MemRegion::VarRegionKind:
+    os << "a variable of type" << TVR->getValueType().getAsString();
+    return true;
+  case MemRegion::FieldRegionKind:
+    os << "a field of type " << TVR->getValueType().getAsString();
+    return true;
+  case MemRegion::ObjCIvarRegionKind:
+    os << "an instance variable of type " << TVR->getValueType().getAsString();
+    return true;
+  default:
+    return false;
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// evaluation of individual function calls.
+//===----------------------------------------------------------------------===//
+
+void CStringChecker::evalCopyCommon(CheckerContext &C, 
+                                    const CallExpr *CE,
+                                    ProgramStateRef state,
+                                    const Expr *Size, const Expr *Dest,
+                                    const Expr *Source, bool Restricted,
+                                    bool IsMempcpy) const {
+  CurrentFunctionDescription = "memory copy function";
+
+  // See if the size argument is zero.
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal sizeVal = state->getSVal(Size, LCtx);
+  QualType sizeTy = Size->getType();
+
+  ProgramStateRef stateZeroSize, stateNonZeroSize;
+  llvm::tie(stateZeroSize, stateNonZeroSize) =
+    assumeZero(C, state, sizeVal, sizeTy);
+
+  // Get the value of the Dest.
+  SVal destVal = state->getSVal(Dest, LCtx);
+
+  // If the size is zero, there won't be any actual memory access, so
+  // just bind the return value to the destination buffer and return.
+  if (stateZeroSize) {
+    stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, destVal);
+    C.addTransition(stateZeroSize);
+  }
+
+  // If the size can be nonzero, we have to check the other arguments.
+  if (stateNonZeroSize) {
+    state = stateNonZeroSize;
+
+    // Ensure the destination is not null. If it is NULL there will be a
+    // NULL pointer dereference.
+    state = checkNonNull(C, state, Dest, destVal);
+    if (!state)
+      return;
+
+    // Get the value of the Src.
+    SVal srcVal = state->getSVal(Source, LCtx);
+    
+    // Ensure the source is not null. If it is NULL there will be a
+    // NULL pointer dereference.
+    state = checkNonNull(C, state, Source, srcVal);
+    if (!state)
+      return;
+
+    // Ensure the accesses are valid and that the buffers do not overlap.
+    const char * const writeWarning =
+      "Memory copy function overflows destination buffer";
+    state = CheckBufferAccess(C, state, Size, Dest, Source,
+                              writeWarning, /* sourceWarning = */ NULL);
+    if (Restricted)
+      state = CheckOverlap(C, state, Size, Dest, Source);
+
+    if (!state)
+      return;
+
+    // If this is mempcpy, get the byte after the last byte copied and 
+    // bind the expr.
+    if (IsMempcpy) {
+      loc::MemRegionVal *destRegVal = dyn_cast<loc::MemRegionVal>(&destVal);
+      assert(destRegVal && "Destination should be a known MemRegionVal here");
+      
+      // Get the length to copy.
+      NonLoc *lenValNonLoc = dyn_cast<NonLoc>(&sizeVal);
+      
+      if (lenValNonLoc) {
+        // Get the byte after the last byte copied.
+        SVal lastElement = C.getSValBuilder().evalBinOpLN(state, BO_Add, 
+                                                          *destRegVal,
+                                                          *lenValNonLoc, 
+                                                          Dest->getType());
+      
+        // The byte after the last byte copied is the return value.
+        state = state->BindExpr(CE, LCtx, lastElement);
+      } else {
+        // If we don't know how much we copied, we can at least
+        // conjure a return value for later.
+        unsigned Count = C.getCurrentBlockCount();
+        SVal result =
+          C.getSValBuilder().getConjuredSymbolVal(NULL, CE, LCtx, Count);
+        state = state->BindExpr(CE, LCtx, result);
+      }
+
+    } else {
+      // All other copies return the destination buffer.
+      // (Well, bcopy() has a void return type, but this won't hurt.)
+      state = state->BindExpr(CE, LCtx, destVal);
+    }
+
+    // Invalidate the destination.
+    // FIXME: Even if we can't perfectly model the copy, we should see if we
+    // can use LazyCompoundVals to copy the source values into the destination.
+    // This would probably remove any existing bindings past the end of the
+    // copied region, but that's still an improvement over blank invalidation.
+    state = InvalidateBuffer(C, state, Dest,
+                             state->getSVal(Dest, C.getLocationContext()));
+    C.addTransition(state);
+  }
+}
+
+
+void CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) const {
+  if (CE->getNumArgs() < 3)
+    return;
+
+  // void *memcpy(void *restrict dst, const void *restrict src, size_t n);
+  // The return value is the address of the destination buffer.
+  const Expr *Dest = CE->getArg(0);
+  ProgramStateRef state = C.getState();
+
+  evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1), true);
+}
+
+void CStringChecker::evalMempcpy(CheckerContext &C, const CallExpr *CE) const {
+  if (CE->getNumArgs() < 3)
+    return;
+
+  // void *mempcpy(void *restrict dst, const void *restrict src, size_t n);
+  // The return value is a pointer to the byte following the last written byte.
+  const Expr *Dest = CE->getArg(0);
+  ProgramStateRef state = C.getState();
+  
+  evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1), true, true);
+}
+
+void CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) const {
+  if (CE->getNumArgs() < 3)
+    return;
+
+  // void *memmove(void *dst, const void *src, size_t n);
+  // The return value is the address of the destination buffer.
+  const Expr *Dest = CE->getArg(0);
+  ProgramStateRef state = C.getState();
+
+  evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1));
+}
+
+void CStringChecker::evalBcopy(CheckerContext &C, const CallExpr *CE) const {
+  if (CE->getNumArgs() < 3)
+    return;
+
+  // void bcopy(const void *src, void *dst, size_t n);
+  evalCopyCommon(C, CE, C.getState(), 
+                 CE->getArg(2), CE->getArg(1), CE->getArg(0));
+}
+
+void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const {
+  if (CE->getNumArgs() < 3)
+    return;
+
+  // int memcmp(const void *s1, const void *s2, size_t n);
+  CurrentFunctionDescription = "memory comparison function";
+
+  const Expr *Left = CE->getArg(0);
+  const Expr *Right = CE->getArg(1);
+  const Expr *Size = CE->getArg(2);
+
+  ProgramStateRef state = C.getState();
+  SValBuilder &svalBuilder = C.getSValBuilder();
+
+  // See if the size argument is zero.
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal sizeVal = state->getSVal(Size, LCtx);
+  QualType sizeTy = Size->getType();
+
+  ProgramStateRef stateZeroSize, stateNonZeroSize;
+  llvm::tie(stateZeroSize, stateNonZeroSize) =
+    assumeZero(C, state, sizeVal, sizeTy);
+
+  // If the size can be zero, the result will be 0 in that case, and we don't
+  // have to check either of the buffers.
+  if (stateZeroSize) {
+    state = stateZeroSize;
+    state = state->BindExpr(CE, LCtx,
+                            svalBuilder.makeZeroVal(CE->getType()));
+    C.addTransition(state);
+  }
+
+  // If the size can be nonzero, we have to check the other arguments.
+  if (stateNonZeroSize) {
+    state = stateNonZeroSize;
+    // If we know the two buffers are the same, we know the result is 0.
+    // First, get the two buffers' addresses. Another checker will have already
+    // made sure they're not undefined.
+    DefinedOrUnknownSVal LV =
+      cast<DefinedOrUnknownSVal>(state->getSVal(Left, LCtx));
+    DefinedOrUnknownSVal RV =
+      cast<DefinedOrUnknownSVal>(state->getSVal(Right, LCtx));
+
+    // See if they are the same.
+    DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV);
+    ProgramStateRef StSameBuf, StNotSameBuf;
+    llvm::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
+
+    // If the two arguments might be the same buffer, we know the result is 0,
+    // and we only need to check one size.
+    if (StSameBuf) {
+      state = StSameBuf;
+      state = CheckBufferAccess(C, state, Size, Left);
+      if (state) {
+        state = StSameBuf->BindExpr(CE, LCtx,
+                                    svalBuilder.makeZeroVal(CE->getType()));
+        C.addTransition(state);
+      }
+    }
+
+    // If the two arguments might be different buffers, we have to check the
+    // size of both of them.
+    if (StNotSameBuf) {
+      state = StNotSameBuf;
+      state = CheckBufferAccess(C, state, Size, Left, Right);
+      if (state) {
+        // The return value is the comparison result, which we don't know.
+        unsigned Count = C.getCurrentBlockCount();
+        SVal CmpV = svalBuilder.getConjuredSymbolVal(NULL, CE, LCtx, Count);
+        state = state->BindExpr(CE, LCtx, CmpV);
+        C.addTransition(state);
+      }
+    }
+  }
+}
+
+void CStringChecker::evalstrLength(CheckerContext &C,
+                                   const CallExpr *CE) const {
+  if (CE->getNumArgs() < 1)
+    return;
+
+  // size_t strlen(const char *s);
+  evalstrLengthCommon(C, CE, /* IsStrnlen = */ false);
+}
+
+void CStringChecker::evalstrnLength(CheckerContext &C,
+                                    const CallExpr *CE) const {
+  if (CE->getNumArgs() < 2)
+    return;
+
+  // size_t strnlen(const char *s, size_t maxlen);
+  evalstrLengthCommon(C, CE, /* IsStrnlen = */ true);
+}
+
+void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE,
+                                         bool IsStrnlen) const {
+  CurrentFunctionDescription = "string length function";
+  ProgramStateRef state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
+
+  if (IsStrnlen) {
+    const Expr *maxlenExpr = CE->getArg(1);
+    SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
+
+    ProgramStateRef stateZeroSize, stateNonZeroSize;
+    llvm::tie(stateZeroSize, stateNonZeroSize) =
+      assumeZero(C, state, maxlenVal, maxlenExpr->getType());
+
+    // If the size can be zero, the result will be 0 in that case, and we don't
+    // have to check the string itself.
+    if (stateZeroSize) {
+      SVal zero = C.getSValBuilder().makeZeroVal(CE->getType());
+      stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, zero);
+      C.addTransition(stateZeroSize);
+    }
+
+    // If the size is GUARANTEED to be zero, we're done!
+    if (!stateNonZeroSize)
+      return;
+
+    // Otherwise, record the assumption that the size is nonzero.
+    state = stateNonZeroSize;
+  }
+
+  // Check that the string argument is non-null.
+  const Expr *Arg = CE->getArg(0);
+  SVal ArgVal = state->getSVal(Arg, LCtx);
+
+  state = checkNonNull(C, state, Arg, ArgVal);
+
+  if (!state)
+    return;
+
+  SVal strLength = getCStringLength(C, state, Arg, ArgVal);
+
+  // If the argument isn't a valid C string, there's no valid state to
+  // transition to.
+  if (strLength.isUndef())
+    return;
+
+  DefinedOrUnknownSVal result = UnknownVal();
+
+  // If the check is for strnlen() then bind the return value to no more than
+  // the maxlen value.
+  if (IsStrnlen) {
+    QualType cmpTy = C.getSValBuilder().getConditionType();
+
+    // It's a little unfortunate to be getting this again,
+    // but it's not that expensive...
+    const Expr *maxlenExpr = CE->getArg(1);
+    SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
+
+    NonLoc *strLengthNL = dyn_cast<NonLoc>(&strLength);
+    NonLoc *maxlenValNL = dyn_cast<NonLoc>(&maxlenVal);
+
+    if (strLengthNL && maxlenValNL) {
+      ProgramStateRef stateStringTooLong, stateStringNotTooLong;
+
+      // Check if the strLength is greater than the maxlen.
+      llvm::tie(stateStringTooLong, stateStringNotTooLong) =
+        state->assume(cast<DefinedOrUnknownSVal>
+                      (C.getSValBuilder().evalBinOpNN(state, BO_GT, 
+                                                      *strLengthNL,
+                                                      *maxlenValNL,
+                                                      cmpTy)));
+
+      if (stateStringTooLong && !stateStringNotTooLong) {
+        // If the string is longer than maxlen, return maxlen.
+        result = *maxlenValNL;
+      } else if (stateStringNotTooLong && !stateStringTooLong) {
+        // If the string is shorter than maxlen, return its length.
+        result = *strLengthNL;
+      }
+    }
+
+    if (result.isUnknown()) {
+      // If we don't have enough information for a comparison, there's
+      // no guarantee the full string length will actually be returned.
+      // All we know is the return value is the min of the string length
+      // and the limit. This is better than nothing.
+      unsigned Count = C.getCurrentBlockCount();
+      result = C.getSValBuilder().getConjuredSymbolVal(NULL, CE, LCtx, Count);
+      NonLoc *resultNL = cast<NonLoc>(&result);
+
+      if (strLengthNL) {
+        state = state->assume(cast<DefinedOrUnknownSVal>
+                              (C.getSValBuilder().evalBinOpNN(state, BO_LE, 
+                                                              *resultNL,
+                                                              *strLengthNL,
+                                                              cmpTy)), true);
+      }
+      
+      if (maxlenValNL) {
+        state = state->assume(cast<DefinedOrUnknownSVal>
+                              (C.getSValBuilder().evalBinOpNN(state, BO_LE, 
+                                                              *resultNL,
+                                                              *maxlenValNL,
+                                                              cmpTy)), true);
+      }
+    }
+
+  } else {
+    // This is a plain strlen(), not strnlen().
+    result = cast<DefinedOrUnknownSVal>(strLength);
+
+    // If we don't know the length of the string, conjure a return
+    // value, so it can be used in constraints, at least.
+    if (result.isUnknown()) {
+      unsigned Count = C.getCurrentBlockCount();
+      result = C.getSValBuilder().getConjuredSymbolVal(NULL, CE, LCtx, Count);
+    }
+  }
+
+  // Bind the return value.
+  assert(!result.isUnknown() && "Should have conjured a value by now");
+  state = state->BindExpr(CE, LCtx, result);
+  C.addTransition(state);
+}
+
+void CStringChecker::evalStrcpy(CheckerContext &C, const CallExpr *CE) const {
+  if (CE->getNumArgs() < 2)
+    return;
+
+  // char *strcpy(char *restrict dst, const char *restrict src);
+  evalStrcpyCommon(C, CE, 
+                   /* returnEnd = */ false, 
+                   /* isBounded = */ false,
+                   /* isAppending = */ false);
+}
+
+void CStringChecker::evalStrncpy(CheckerContext &C, const CallExpr *CE) const {
+  if (CE->getNumArgs() < 3)
+    return;
+
+  // char *strncpy(char *restrict dst, const char *restrict src, size_t n);
+  evalStrcpyCommon(C, CE, 
+                   /* returnEnd = */ false, 
+                   /* isBounded = */ true,
+                   /* isAppending = */ false);
+}
+
+void CStringChecker::evalStpcpy(CheckerContext &C, const CallExpr *CE) const {
+  if (CE->getNumArgs() < 2)
+    return;
+
+  // char *stpcpy(char *restrict dst, const char *restrict src);
+  evalStrcpyCommon(C, CE, 
+                   /* returnEnd = */ true, 
+                   /* isBounded = */ false,
+                   /* isAppending = */ false);
+}
+
+void CStringChecker::evalStrcat(CheckerContext &C, const CallExpr *CE) const {
+  if (CE->getNumArgs() < 2)
+    return;
+
+  //char *strcat(char *restrict s1, const char *restrict s2);
+  evalStrcpyCommon(C, CE, 
+                   /* returnEnd = */ false, 
+                   /* isBounded = */ false,
+                   /* isAppending = */ true);
+}
+
+void CStringChecker::evalStrncat(CheckerContext &C, const CallExpr *CE) const {
+  if (CE->getNumArgs() < 3)
+    return;
+
+  //char *strncat(char *restrict s1, const char *restrict s2, size_t n);
+  evalStrcpyCommon(C, CE, 
+                   /* returnEnd = */ false, 
+                   /* isBounded = */ true,
+                   /* isAppending = */ true);
+}
+
+void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
+                                      bool returnEnd, bool isBounded,
+                                      bool isAppending) const {
+  CurrentFunctionDescription = "string copy function";
+  ProgramStateRef state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
+
+  // Check that the destination is non-null.
+  const Expr *Dst = CE->getArg(0);
+  SVal DstVal = state->getSVal(Dst, LCtx);
+
+  state = checkNonNull(C, state, Dst, DstVal);
+  if (!state)
+    return;
+
+  // Check that the source is non-null.
+  const Expr *srcExpr = CE->getArg(1);
+  SVal srcVal = state->getSVal(srcExpr, LCtx);
+  state = checkNonNull(C, state, srcExpr, srcVal);
+  if (!state)
+    return;
+
+  // Get the string length of the source.
+  SVal strLength = getCStringLength(C, state, srcExpr, srcVal);
+
+  // If the source isn't a valid C string, give up.
+  if (strLength.isUndef())
+    return;
+
+  SValBuilder &svalBuilder = C.getSValBuilder();
+  QualType cmpTy = svalBuilder.getConditionType();
+  QualType sizeTy = svalBuilder.getContext().getSizeType();
+
+  // These two values allow checking two kinds of errors:
+  // - actual overflows caused by a source that doesn't fit in the destination
+  // - potential overflows caused by a bound that could exceed the destination
+  SVal amountCopied = UnknownVal();
+  SVal maxLastElementIndex = UnknownVal();
+  const char *boundWarning = NULL;
+
+  // If the function is strncpy, strncat, etc... it is bounded.
+  if (isBounded) {
+    // Get the max number of characters to copy.
+    const Expr *lenExpr = CE->getArg(2);
+    SVal lenVal = state->getSVal(lenExpr, LCtx);
+
+    // Protect against misdeclared strncpy().
+    lenVal = svalBuilder.evalCast(lenVal, sizeTy, lenExpr->getType());
+
+    NonLoc *strLengthNL = dyn_cast<NonLoc>(&strLength);
+    NonLoc *lenValNL = dyn_cast<NonLoc>(&lenVal);
+
+    // If we know both values, we might be able to figure out how much
+    // we're copying.
+    if (strLengthNL && lenValNL) {
+      ProgramStateRef stateSourceTooLong, stateSourceNotTooLong;
+
+      // Check if the max number to copy is less than the length of the src.
+      // If the bound is equal to the source length, strncpy won't null-
+      // terminate the result!
+      llvm::tie(stateSourceTooLong, stateSourceNotTooLong) =
+        state->assume(cast<DefinedOrUnknownSVal>
+                      (svalBuilder.evalBinOpNN(state, BO_GE, *strLengthNL,
+                                               *lenValNL, cmpTy)));
+
+      if (stateSourceTooLong && !stateSourceNotTooLong) {
+        // Max number to copy is less than the length of the src, so the actual
+        // strLength copied is the max number arg.
+        state = stateSourceTooLong;
+        amountCopied = lenVal;
+
+      } else if (!stateSourceTooLong && stateSourceNotTooLong) {
+        // The source buffer entirely fits in the bound.
+        state = stateSourceNotTooLong;
+        amountCopied = strLength;
+      }
+    }
+
+    // We still want to know if the bound is known to be too large.
+    if (lenValNL) {
+      if (isAppending) {
+        // For strncat, the check is strlen(dst) + lenVal < sizeof(dst)
+
+        // Get the string length of the destination. If the destination is
+        // memory that can't have a string length, we shouldn't be copying
+        // into it anyway.
+        SVal dstStrLength = getCStringLength(C, state, Dst, DstVal);
+        if (dstStrLength.isUndef())
+          return;
+
+        if (NonLoc *dstStrLengthNL = dyn_cast<NonLoc>(&dstStrLength)) {
+          maxLastElementIndex = svalBuilder.evalBinOpNN(state, BO_Add,
+                                                        *lenValNL,
+                                                        *dstStrLengthNL,
+                                                        sizeTy);
+          boundWarning = "Size argument is greater than the free space in the "
+                         "destination buffer";
+        }
+
+      } else {
+        // For strncpy, this is just checking that lenVal <= sizeof(dst)
+        // (Yes, strncpy and strncat differ in how they treat termination.
+        // strncat ALWAYS terminates, but strncpy doesn't.)
+        NonLoc one = cast<NonLoc>(svalBuilder.makeIntVal(1, sizeTy));
+        maxLastElementIndex = svalBuilder.evalBinOpNN(state, BO_Sub, *lenValNL,
+                                                      one, sizeTy);
+        boundWarning = "Size argument is greater than the length of the "
+                       "destination buffer";
+      }
+    }
+
+    // If we couldn't pin down the copy length, at least bound it.
+    // FIXME: We should actually run this code path for append as well, but
+    // right now it creates problems with constraints (since we can end up
+    // trying to pass constraints from symbol to symbol).
+    if (amountCopied.isUnknown() && !isAppending) {
+      // Try to get a "hypothetical" string length symbol, which we can later
+      // set as a real value if that turns out to be the case.
+      amountCopied = getCStringLength(C, state, lenExpr, srcVal, true);
+      assert(!amountCopied.isUndef());
+
+      if (NonLoc *amountCopiedNL = dyn_cast<NonLoc>(&amountCopied)) {
+        if (lenValNL) {
+          // amountCopied <= lenVal
+          SVal copiedLessThanBound = svalBuilder.evalBinOpNN(state, BO_LE,
+                                                             *amountCopiedNL,
+                                                             *lenValNL,
+                                                             cmpTy);
+          state = state->assume(cast<DefinedOrUnknownSVal>(copiedLessThanBound),
+                                true);
+          if (!state)
+            return;
+        }
+
+        if (strLengthNL) {
+          // amountCopied <= strlen(source)
+          SVal copiedLessThanSrc = svalBuilder.evalBinOpNN(state, BO_LE,
+                                                           *amountCopiedNL,
+                                                           *strLengthNL,
+                                                           cmpTy);
+          state = state->assume(cast<DefinedOrUnknownSVal>(copiedLessThanSrc),
+                                true);
+          if (!state)
+            return;
+        }
+      }
+    }
+
+  } else {
+    // The function isn't bounded. The amount copied should match the length
+    // of the source buffer.
+    amountCopied = strLength;
+  }
+
+  assert(state);
+
+  // This represents the number of characters copied into the destination
+  // buffer. (It may not actually be the strlen if the destination buffer
+  // is not terminated.)
+  SVal finalStrLength = UnknownVal();
+
+  // If this is an appending function (strcat, strncat...) then set the
+  // string length to strlen(src) + strlen(dst) since the buffer will
+  // ultimately contain both.
+  if (isAppending) {
+    // Get the string length of the destination. If the destination is memory
+    // that can't have a string length, we shouldn't be copying into it anyway.
+    SVal dstStrLength = getCStringLength(C, state, Dst, DstVal);
+    if (dstStrLength.isUndef())
+      return;
+
+    NonLoc *srcStrLengthNL = dyn_cast<NonLoc>(&amountCopied);
+    NonLoc *dstStrLengthNL = dyn_cast<NonLoc>(&dstStrLength);
+    
+    // If we know both string lengths, we might know the final string length.
+    if (srcStrLengthNL && dstStrLengthNL) {
+      // Make sure the two lengths together don't overflow a size_t.
+      state = checkAdditionOverflow(C, state, *srcStrLengthNL, *dstStrLengthNL);
+      if (!state)
+        return;
+
+      finalStrLength = svalBuilder.evalBinOpNN(state, BO_Add, *srcStrLengthNL, 
+                                               *dstStrLengthNL, sizeTy);
+    }
+
+    // If we couldn't get a single value for the final string length,
+    // we can at least bound it by the individual lengths.
+    if (finalStrLength.isUnknown()) {
+      // Try to get a "hypothetical" string length symbol, which we can later
+      // set as a real value if that turns out to be the case.
+      finalStrLength = getCStringLength(C, state, CE, DstVal, true);
+      assert(!finalStrLength.isUndef());
+
+      if (NonLoc *finalStrLengthNL = dyn_cast<NonLoc>(&finalStrLength)) {
+        if (srcStrLengthNL) {
+          // finalStrLength >= srcStrLength
+          SVal sourceInResult = svalBuilder.evalBinOpNN(state, BO_GE,
+                                                        *finalStrLengthNL,
+                                                        *srcStrLengthNL,
+                                                        cmpTy);
+          state = state->assume(cast<DefinedOrUnknownSVal>(sourceInResult),
+                                true);
+          if (!state)
+            return;
+        }
+
+        if (dstStrLengthNL) {
+          // finalStrLength >= dstStrLength
+          SVal destInResult = svalBuilder.evalBinOpNN(state, BO_GE,
+                                                      *finalStrLengthNL,
+                                                      *dstStrLengthNL,
+                                                      cmpTy);
+          state = state->assume(cast<DefinedOrUnknownSVal>(destInResult),
+                                true);
+          if (!state)
+            return;
+        }
+      }
+    }
+
+  } else {
+    // Otherwise, this is a copy-over function (strcpy, strncpy, ...), and
+    // the final string length will match the input string length.
+    finalStrLength = amountCopied;
+  }
+
+  // The final result of the function will either be a pointer past the last
+  // copied element, or a pointer to the start of the destination buffer.
+  SVal Result = (returnEnd ? UnknownVal() : DstVal);
+
+  assert(state);
+
+  // If the destination is a MemRegion, try to check for a buffer overflow and
+  // record the new string length.
+  if (loc::MemRegionVal *dstRegVal = dyn_cast<loc::MemRegionVal>(&DstVal)) {
+    QualType ptrTy = Dst->getType();
+
+    // If we have an exact value on a bounded copy, use that to check for
+    // overflows, rather than our estimate about how much is actually copied.
+    if (boundWarning) {
+      if (NonLoc *maxLastNL = dyn_cast<NonLoc>(&maxLastElementIndex)) {
+        SVal maxLastElement = svalBuilder.evalBinOpLN(state, BO_Add, *dstRegVal,
+                                                      *maxLastNL, ptrTy);
+        state = CheckLocation(C, state, CE->getArg(2), maxLastElement, 
+                              boundWarning);
+        if (!state)
+          return;
+      }
+    }
+
+    // Then, if the final length is known...
+    if (NonLoc *knownStrLength = dyn_cast<NonLoc>(&finalStrLength)) {
+      SVal lastElement = svalBuilder.evalBinOpLN(state, BO_Add, *dstRegVal,
+                                                 *knownStrLength, ptrTy);
+
+      // ...and we haven't checked the bound, we'll check the actual copy.
+      if (!boundWarning) {
+        const char * const warningMsg =
+          "String copy function overflows destination buffer";
+        state = CheckLocation(C, state, Dst, lastElement, warningMsg);
+        if (!state)
+          return;
+      }
+
+      // If this is a stpcpy-style copy, the last element is the return value.
+      if (returnEnd)
+        Result = lastElement;
+    }
+
+    // Invalidate the destination. This must happen before we set the C string
+    // length because invalidation will clear the length.
+    // FIXME: Even if we can't perfectly model the copy, we should see if we
+    // can use LazyCompoundVals to copy the source values into the destination.
+    // This would probably remove any existing bindings past the end of the
+    // string, but that's still an improvement over blank invalidation.
+    state = InvalidateBuffer(C, state, Dst, *dstRegVal);
+
+    // Set the C string length of the destination, if we know it.
+    if (isBounded && !isAppending) {
+      // strncpy is annoying in that it doesn't guarantee to null-terminate
+      // the result string. If the original string didn't fit entirely inside
+      // the bound (including the null-terminator), we don't know how long the
+      // result is.
+      if (amountCopied != strLength)
+        finalStrLength = UnknownVal();
+    }
+    state = setCStringLength(state, dstRegVal->getRegion(), finalStrLength);
+  }
+
+  assert(state);
+
+  // If this is a stpcpy-style copy, but we were unable to check for a buffer
+  // overflow, we still need a result. Conjure a return value.
+  if (returnEnd && Result.isUnknown()) {
+    unsigned Count = C.getCurrentBlockCount();
+    Result = svalBuilder.getConjuredSymbolVal(NULL, CE, LCtx, Count);
+  }
+
+  // Set the return value.
+  state = state->BindExpr(CE, LCtx, Result);
+  C.addTransition(state);
+}
+
+void CStringChecker::evalStrcmp(CheckerContext &C, const CallExpr *CE) const {
+  if (CE->getNumArgs() < 2)
+    return;
+
+  //int strcmp(const char *s1, const char *s2);
+  evalStrcmpCommon(C, CE, /* isBounded = */ false, /* ignoreCase = */ false);
+}
+
+void CStringChecker::evalStrncmp(CheckerContext &C, const CallExpr *CE) const {
+  if (CE->getNumArgs() < 3)
+    return;
+
+  //int strncmp(const char *s1, const char *s2, size_t n);
+  evalStrcmpCommon(C, CE, /* isBounded = */ true, /* ignoreCase = */ false);
+}
+
+void CStringChecker::evalStrcasecmp(CheckerContext &C, 
+                                    const CallExpr *CE) const {
+  if (CE->getNumArgs() < 2)
+    return;
+
+  //int strcasecmp(const char *s1, const char *s2);
+  evalStrcmpCommon(C, CE, /* isBounded = */ false, /* ignoreCase = */ true);
+}
+
+void CStringChecker::evalStrncasecmp(CheckerContext &C, 
+                                     const CallExpr *CE) const {
+  if (CE->getNumArgs() < 3)
+    return;
+
+  //int strncasecmp(const char *s1, const char *s2, size_t n);
+  evalStrcmpCommon(C, CE, /* isBounded = */ true, /* ignoreCase = */ true);
+}
+
+void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
+                                      bool isBounded, bool ignoreCase) const {
+  CurrentFunctionDescription = "string comparison function";
+  ProgramStateRef state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
+
+  // Check that the first string is non-null
+  const Expr *s1 = CE->getArg(0);
+  SVal s1Val = state->getSVal(s1, LCtx);
+  state = checkNonNull(C, state, s1, s1Val);
+  if (!state)
+    return;
+
+  // Check that the second string is non-null.
+  const Expr *s2 = CE->getArg(1);
+  SVal s2Val = state->getSVal(s2, LCtx);
+  state = checkNonNull(C, state, s2, s2Val);
+  if (!state)
+    return;
+
+  // Get the string length of the first string or give up.
+  SVal s1Length = getCStringLength(C, state, s1, s1Val);
+  if (s1Length.isUndef())
+    return;
+
+  // Get the string length of the second string or give up.
+  SVal s2Length = getCStringLength(C, state, s2, s2Val);
+  if (s2Length.isUndef())
+    return;
+
+  // If we know the two buffers are the same, we know the result is 0.
+  // First, get the two buffers' addresses. Another checker will have already
+  // made sure they're not undefined.
+  DefinedOrUnknownSVal LV = cast<DefinedOrUnknownSVal>(s1Val);
+  DefinedOrUnknownSVal RV = cast<DefinedOrUnknownSVal>(s2Val);
+
+  // See if they are the same.
+  SValBuilder &svalBuilder = C.getSValBuilder();
+  DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV);
+  ProgramStateRef StSameBuf, StNotSameBuf;
+  llvm::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
+
+  // If the two arguments might be the same buffer, we know the result is 0,
+  // and we only need to check one size.
+  if (StSameBuf) {
+    StSameBuf = StSameBuf->BindExpr(CE, LCtx,
+                                    svalBuilder.makeZeroVal(CE->getType()));
+    C.addTransition(StSameBuf);
+
+    // If the two arguments are GUARANTEED to be the same, we're done!
+    if (!StNotSameBuf)
+      return;
+  }
+
+  assert(StNotSameBuf);
+  state = StNotSameBuf;
+
+  // At this point we can go about comparing the two buffers.
+  // For now, we only do this if they're both known string literals.
+
+  // Attempt to extract string literals from both expressions.
+  const StringLiteral *s1StrLiteral = getCStringLiteral(C, state, s1, s1Val);
+  const StringLiteral *s2StrLiteral = getCStringLiteral(C, state, s2, s2Val);
+  bool canComputeResult = false;
+
+  if (s1StrLiteral && s2StrLiteral) {
+    StringRef s1StrRef = s1StrLiteral->getString();
+    StringRef s2StrRef = s2StrLiteral->getString();
+
+    if (isBounded) {
+      // Get the max number of characters to compare.
+      const Expr *lenExpr = CE->getArg(2);
+      SVal lenVal = state->getSVal(lenExpr, LCtx);
+
+      // If the length is known, we can get the right substrings.
+      if (const llvm::APSInt *len = svalBuilder.getKnownValue(state, lenVal)) {
+        // Create substrings of each to compare the prefix.
+        s1StrRef = s1StrRef.substr(0, (size_t)len->getZExtValue());
+        s2StrRef = s2StrRef.substr(0, (size_t)len->getZExtValue());
+        canComputeResult = true;
+      }
+    } else {
+      // This is a normal, unbounded strcmp.
+      canComputeResult = true;
+    }
+
+    if (canComputeResult) {
+      // Real strcmp stops at null characters.
+      size_t s1Term = s1StrRef.find('\0');
+      if (s1Term != StringRef::npos)
+        s1StrRef = s1StrRef.substr(0, s1Term);
+
+      size_t s2Term = s2StrRef.find('\0');
+      if (s2Term != StringRef::npos)
+        s2StrRef = s2StrRef.substr(0, s2Term);
+
+      // Use StringRef's comparison methods to compute the actual result.
+      int result;
+
+      if (ignoreCase) {
+        // Compare string 1 to string 2 the same way strcasecmp() does.
+        result = s1StrRef.compare_lower(s2StrRef);
+      } else {
+        // Compare string 1 to string 2 the same way strcmp() does.
+        result = s1StrRef.compare(s2StrRef);
+      }
+
+      // Build the SVal of the comparison and bind the return value.
+      SVal resultVal = svalBuilder.makeIntVal(result, CE->getType());
+      state = state->BindExpr(CE, LCtx, resultVal);
+    }
+  }
+
+  if (!canComputeResult) {
+    // Conjure a symbolic value. It's the best we can do.
+    unsigned Count = C.getCurrentBlockCount();
+    SVal resultVal = svalBuilder.getConjuredSymbolVal(NULL, CE, LCtx, Count);
+    state = state->BindExpr(CE, LCtx, resultVal);
+  }
+
+  // Record this as a possible path.
+  C.addTransition(state);
+}
+
+//===----------------------------------------------------------------------===//
+// The driver method, and other Checker callbacks.
+//===----------------------------------------------------------------------===//
+
+bool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
+  const FunctionDecl *FDecl = C.getCalleeDecl(CE);
+
+  if (!FDecl)
+    return false;
+
+  FnCheck evalFunction = 0;
+  if (C.isCLibraryFunction(FDecl, "memcpy"))
+    evalFunction =  &CStringChecker::evalMemcpy;
+  else if (C.isCLibraryFunction(FDecl, "mempcpy"))
+    evalFunction =  &CStringChecker::evalMempcpy;
+  else if (C.isCLibraryFunction(FDecl, "memcmp"))
+    evalFunction =  &CStringChecker::evalMemcmp;
+  else if (C.isCLibraryFunction(FDecl, "memmove"))
+    evalFunction =  &CStringChecker::evalMemmove;
+  else if (C.isCLibraryFunction(FDecl, "strcpy"))
+    evalFunction =  &CStringChecker::evalStrcpy;
+  else if (C.isCLibraryFunction(FDecl, "strncpy"))
+    evalFunction =  &CStringChecker::evalStrncpy;
+  else if (C.isCLibraryFunction(FDecl, "stpcpy"))
+    evalFunction =  &CStringChecker::evalStpcpy;
+  else if (C.isCLibraryFunction(FDecl, "strcat"))
+    evalFunction =  &CStringChecker::evalStrcat;
+  else if (C.isCLibraryFunction(FDecl, "strncat"))
+    evalFunction =  &CStringChecker::evalStrncat;
+  else if (C.isCLibraryFunction(FDecl, "strlen"))
+    evalFunction =  &CStringChecker::evalstrLength;
+  else if (C.isCLibraryFunction(FDecl, "strnlen"))
+    evalFunction =  &CStringChecker::evalstrnLength;
+  else if (C.isCLibraryFunction(FDecl, "strcmp"))
+    evalFunction =  &CStringChecker::evalStrcmp;
+  else if (C.isCLibraryFunction(FDecl, "strncmp"))
+    evalFunction =  &CStringChecker::evalStrncmp;
+  else if (C.isCLibraryFunction(FDecl, "strcasecmp"))
+    evalFunction =  &CStringChecker::evalStrcasecmp;
+  else if (C.isCLibraryFunction(FDecl, "strncasecmp"))
+    evalFunction =  &CStringChecker::evalStrncasecmp;
+  else if (C.isCLibraryFunction(FDecl, "bcopy"))
+    evalFunction =  &CStringChecker::evalBcopy;
+  else if (C.isCLibraryFunction(FDecl, "bcmp"))
+    evalFunction =  &CStringChecker::evalMemcmp;
+  
+  // If the callee isn't a string function, let another checker handle it.
+  if (!evalFunction)
+    return false;
+
+  // Make sure each function sets its own description.
+  // (But don't bother in a release build.)
+  assert(!(CurrentFunctionDescription = NULL));
+
+  // Check and evaluate the call.
+  (this->*evalFunction)(C, CE);
+
+  // If the evaluate call resulted in no change, chain to the next eval call
+  // handler.
+  // Note, the custom CString evaluation calls assume that basic safety
+  // properties are held. However, if the user chooses to turn off some of these
+  // checks, we ignore the issues and leave the call evaluation to a generic
+  // handler.
+  if (!C.isDifferent())
+    return false;
+
+  return true;
+}
+
+void CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
+  // Record string length for char a[] = "abc";
+  ProgramStateRef state = C.getState();
+
+  for (DeclStmt::const_decl_iterator I = DS->decl_begin(), E = DS->decl_end();
+       I != E; ++I) {
+    const VarDecl *D = dyn_cast<VarDecl>(*I);
+    if (!D)
+      continue;
+
+    // FIXME: Handle array fields of structs.
+    if (!D->getType()->isArrayType())
+      continue;
+
+    const Expr *Init = D->getInit();
+    if (!Init)
+      continue;
+    if (!isa<StringLiteral>(Init))
+      continue;
+
+    Loc VarLoc = state->getLValue(D, C.getLocationContext());
+    const MemRegion *MR = VarLoc.getAsRegion();
+    if (!MR)
+      continue;
+
+    SVal StrVal = state->getSVal(Init, C.getLocationContext());
+    assert(StrVal.isValid() && "Initializer string is unknown or undefined");
+    DefinedOrUnknownSVal strLength
+      = cast<DefinedOrUnknownSVal>(getCStringLength(C, state, Init, StrVal));
+
+    state = state->set<CStringLength>(MR, strLength);
+  }
+
+  C.addTransition(state);
+}
+
+bool CStringChecker::wantsRegionChangeUpdate(ProgramStateRef state) const {
+  CStringLength::EntryMap Entries = state->get<CStringLength>();
+  return !Entries.isEmpty();
+}
+
+ProgramStateRef 
+CStringChecker::checkRegionChanges(ProgramStateRef state,
+                                   const StoreManager::InvalidatedSymbols *,
+                                   ArrayRef<const MemRegion *> ExplicitRegions,
+                                   ArrayRef<const MemRegion *> Regions,
+                                   const CallOrObjCMessage *Call) const {
+  CStringLength::EntryMap Entries = state->get<CStringLength>();
+  if (Entries.isEmpty())
+    return state;
+
+  llvm::SmallPtrSet<const MemRegion *, 8> Invalidated;
+  llvm::SmallPtrSet<const MemRegion *, 32> SuperRegions;
+
+  // First build sets for the changed regions and their super-regions.
+  for (ArrayRef<const MemRegion *>::iterator
+       I = Regions.begin(), E = Regions.end(); I != E; ++I) {
+    const MemRegion *MR = *I;
+    Invalidated.insert(MR);
+
+    SuperRegions.insert(MR);
+    while (const SubRegion *SR = dyn_cast<SubRegion>(MR)) {
+      MR = SR->getSuperRegion();
+      SuperRegions.insert(MR);
+    }
+  }
+
+  CStringLength::EntryMap::Factory &F = state->get_context<CStringLength>();
+
+  // Then loop over the entries in the current state.
+  for (CStringLength::EntryMap::iterator I = Entries.begin(),
+       E = Entries.end(); I != E; ++I) {
+    const MemRegion *MR = I.getKey();
+
+    // Is this entry for a super-region of a changed region?
+    if (SuperRegions.count(MR)) {
+      Entries = F.remove(Entries, MR);
+      continue;
+    }
+
+    // Is this entry for a sub-region of a changed region?
+    const MemRegion *Super = MR;
+    while (const SubRegion *SR = dyn_cast<SubRegion>(Super)) {
+      Super = SR->getSuperRegion();
+      if (Invalidated.count(Super)) {
+        Entries = F.remove(Entries, MR);
+        break;
+      }
+    }
+  }
+
+  return state->set<CStringLength>(Entries);
+}
+
+void CStringChecker::checkLiveSymbols(ProgramStateRef state,
+                                      SymbolReaper &SR) const {
+  // Mark all symbols in our string length map as valid.
+  CStringLength::EntryMap Entries = state->get<CStringLength>();
+
+  for (CStringLength::EntryMap::iterator I = Entries.begin(), E = Entries.end();
+       I != E; ++I) {
+    SVal Len = I.getData();
+
+    for (SymExpr::symbol_iterator si = Len.symbol_begin(),
+                                  se = Len.symbol_end(); si != se; ++si)
+      SR.markInUse(*si);
+  }
+}
+
+void CStringChecker::checkDeadSymbols(SymbolReaper &SR,
+                                      CheckerContext &C) const {
+  if (!SR.hasDeadSymbols())
+    return;
+
+  ProgramStateRef state = C.getState();
+  CStringLength::EntryMap Entries = state->get<CStringLength>();
+  if (Entries.isEmpty())
+    return;
+
+  CStringLength::EntryMap::Factory &F = state->get_context<CStringLength>();
+  for (CStringLength::EntryMap::iterator I = Entries.begin(), E = Entries.end();
+       I != E; ++I) {
+    SVal Len = I.getData();
+    if (SymbolRef Sym = Len.getAsSymbol()) {
+      if (SR.isDead(Sym))
+        Entries = F.remove(Entries, I.getKey());
+    }
+  }
+
+  state = state->set<CStringLength>(Entries);
+  C.addTransition(state);
+}
+
+#define REGISTER_CHECKER(name) \
+void ento::register##name(CheckerManager &mgr) {\
+  static CStringChecker *TheChecker = 0; \
+  if (TheChecker == 0) \
+    TheChecker = mgr.registerChecker<CStringChecker>(); \
+  TheChecker->Filter.Check##name = true; \
+}
+
+REGISTER_CHECKER(CStringNullArg)
+REGISTER_CHECKER(CStringOutOfBounds)
+REGISTER_CHECKER(CStringBufferOverlap)
+REGISTER_CHECKER(CStringNotNullTerm)
+
+void ento::registerCStringCheckerBasic(CheckerManager &Mgr) {
+  registerCStringNullArg(Mgr);
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
new file mode 100644
index 0000000..befc935
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
@@ -0,0 +1,191 @@
+//== CStringSyntaxChecker.cpp - CoreFoundation containers API *- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// An AST checker that looks for common pitfalls when using C string APIs.
+//  - Identifies erroneous patterns in the last argument to strncat - the number
+//    of bytes to copy.
+//
+//===----------------------------------------------------------------------===//
+#include "ClangSACheckers.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/OperationKinds.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TypeTraits.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class WalkAST: public StmtVisitor<WalkAST> {
+  BugReporter &BR;
+  AnalysisDeclContext* AC;
+  ASTContext &ASTC;
+
+  /// Check if two expressions refer to the same declaration.
+  inline bool sameDecl(const Expr *A1, const Expr *A2) {
+    if (const DeclRefExpr *D1 = dyn_cast<DeclRefExpr>(A1->IgnoreParenCasts()))
+      if (const DeclRefExpr *D2 = dyn_cast<DeclRefExpr>(A2->IgnoreParenCasts()))
+        return D1->getDecl() == D2->getDecl();
+    return false;
+  }
+
+  /// Check if the expression E is a sizeof(WithArg).
+  inline bool isSizeof(const Expr *E, const Expr *WithArg) {
+    if (const UnaryExprOrTypeTraitExpr *UE =
+    dyn_cast<UnaryExprOrTypeTraitExpr>(E))
+      if (UE->getKind() == UETT_SizeOf)
+        return sameDecl(UE->getArgumentExpr(), WithArg);
+    return false;
+  }
+
+  /// Check if the expression E is a strlen(WithArg).
+  inline bool isStrlen(const Expr *E, const Expr *WithArg) {
+    if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
+      const FunctionDecl *FD = CE->getDirectCallee();
+      if (!FD)
+        return false;
+      return (CheckerContext::isCLibraryFunction(FD, "strlen", ASTC)
+          && sameDecl(CE->getArg(0), WithArg));
+    }
+    return false;
+  }
+
+  /// Check if the expression is an integer literal with value 1.
+  inline bool isOne(const Expr *E) {
+    if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(E))
+      return (IL->getValue().isIntN(1));
+    return false;
+  }
+
+  inline StringRef getPrintableName(const Expr *E) {
+    if (const DeclRefExpr *D = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
+      return D->getDecl()->getName();
+    return StringRef();
+  }
+
+  /// Identify erroneous patterns in the last argument to strncat - the number
+  /// of bytes to copy.
+  bool containsBadStrncatPattern(const CallExpr *CE);
+
+public:
+  WalkAST(BugReporter &br, AnalysisDeclContext* ac) :
+      BR(br), AC(ac), ASTC(AC->getASTContext()) {
+  }
+
+  // Statement visitor methods.
+  void VisitChildren(Stmt *S);
+  void VisitStmt(Stmt *S) {
+    VisitChildren(S);
+  }
+  void VisitCallExpr(CallExpr *CE);
+};
+} // end anonymous namespace
+
+// The correct size argument should look like following:
+//   strncat(dst, src, sizeof(dst) - strlen(dest) - 1);
+// We look for the following anti-patterns:
+//   - strncat(dst, src, sizeof(dst) - strlen(dst));
+//   - strncat(dst, src, sizeof(dst) - 1);
+//   - strncat(dst, src, sizeof(dst));
+bool WalkAST::containsBadStrncatPattern(const CallExpr *CE) {
+  const Expr *DstArg = CE->getArg(0);
+  const Expr *SrcArg = CE->getArg(1);
+  const Expr *LenArg = CE->getArg(2);
+
+  // Identify wrong size expressions, which are commonly used instead.
+  if (const BinaryOperator *BE =
+              dyn_cast<BinaryOperator>(LenArg->IgnoreParenCasts())) {
+    // - sizeof(dst) - strlen(dst)
+    if (BE->getOpcode() == BO_Sub) {
+      const Expr *L = BE->getLHS();
+      const Expr *R = BE->getRHS();
+      if (isSizeof(L, DstArg) && isStrlen(R, DstArg))
+        return true;
+
+      // - sizeof(dst) - 1
+      if (isSizeof(L, DstArg) && isOne(R->IgnoreParenCasts()))
+        return true;
+    }
+  }
+  // - sizeof(dst)
+  if (isSizeof(LenArg, DstArg))
+    return true;
+
+  // - sizeof(src)
+  if (isSizeof(LenArg, SrcArg))
+    return true;
+  return false;
+}
+
+void WalkAST::VisitCallExpr(CallExpr *CE) {
+  const FunctionDecl *FD = CE->getDirectCallee();
+  if (!FD)
+    return;
+
+  if (CheckerContext::isCLibraryFunction(FD, "strncat", ASTC)) {
+    if (containsBadStrncatPattern(CE)) {
+      const Expr *DstArg = CE->getArg(0);
+      const Expr *LenArg = CE->getArg(2);
+      SourceRange R = LenArg->getSourceRange();
+      PathDiagnosticLocation Loc =
+        PathDiagnosticLocation::createBegin(LenArg, BR.getSourceManager(), AC);
+
+      StringRef DstName = getPrintableName(DstArg);
+
+      SmallString<256> S;
+      llvm::raw_svector_ostream os(S);
+      os << "Potential buffer overflow. ";
+      if (!DstName.empty()) {
+        os << "Replace with 'sizeof(" << DstName << ") "
+              "- strlen(" << DstName <<") - 1'";
+        os << " or u";
+      } else
+        os << "U";
+      os << "se a safer 'strlcat' API";
+
+      BR.EmitBasicReport(FD, "Anti-pattern in the argument", "C String API",
+                         os.str(), Loc, &R, 1);
+    }
+  }
+
+  // Recurse and check children.
+  VisitChildren(CE);
+}
+
+void WalkAST::VisitChildren(Stmt *S) {
+  for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I != E;
+      ++I)
+    if (Stmt *child = *I)
+      Visit(child);
+}
+
+namespace {
+class CStringSyntaxChecker: public Checker<check::ASTCodeBody> {
+public:
+
+  void checkASTCodeBody(const Decl *D, AnalysisManager& Mgr,
+      BugReporter &BR) const {
+    WalkAST walker(BR, Mgr.getAnalysisDeclContext(D));
+    walker.Visit(D->getBody());
+  }
+};
+}
+
+void ento::registerCStringSyntaxChecker(CheckerManager &mgr) {
+  mgr.registerChecker<CStringSyntaxChecker>();
+}
+
diff --git a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
new file mode 100644
index 0000000..f601431
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
@@ -0,0 +1,385 @@
+//===--- CallAndMessageChecker.cpp ------------------------------*- C++ -*--==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines CallAndMessageChecker, a builtin checker that checks for various
+// errors of call and objc message expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class CallAndMessageChecker
+  : public Checker< check::PreStmt<CallExpr>, check::PreObjCMessage > {
+  mutable OwningPtr<BugType> BT_call_null;
+  mutable OwningPtr<BugType> BT_call_undef;
+  mutable OwningPtr<BugType> BT_call_arg;
+  mutable OwningPtr<BugType> BT_msg_undef;
+  mutable OwningPtr<BugType> BT_objc_prop_undef;
+  mutable OwningPtr<BugType> BT_msg_arg;
+  mutable OwningPtr<BugType> BT_msg_ret;
+public:
+
+  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
+  void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const;
+
+private:
+  static void PreVisitProcessArgs(CheckerContext &C,CallOrObjCMessage callOrMsg,
+                             const char *BT_desc, OwningPtr<BugType> &BT);
+  static bool PreVisitProcessArg(CheckerContext &C, SVal V,SourceRange argRange,
+                                 const Expr *argEx,
+                                 const bool checkUninitFields,
+                                 const char *BT_desc,
+                                 OwningPtr<BugType> &BT);
+
+  static void EmitBadCall(BugType *BT, CheckerContext &C, const CallExpr *CE);
+  void emitNilReceiverBug(CheckerContext &C, const ObjCMessage &msg,
+                          ExplodedNode *N) const;
+
+  void HandleNilReceiver(CheckerContext &C,
+                         ProgramStateRef state,
+                         ObjCMessage msg) const;
+
+  static void LazyInit_BT(const char *desc, OwningPtr<BugType> &BT) {
+    if (!BT)
+      BT.reset(new BuiltinBug(desc));
+  }
+};
+} // end anonymous namespace
+
+void CallAndMessageChecker::EmitBadCall(BugType *BT, CheckerContext &C,
+                                        const CallExpr *CE) {
+  ExplodedNode *N = C.generateSink();
+  if (!N)
+    return;
+
+  BugReport *R = new BugReport(*BT, BT->getName(), N);
+  R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
+                               bugreporter::GetCalleeExpr(N), R));
+  C.EmitReport(R);
+}
+
+void CallAndMessageChecker::PreVisitProcessArgs(CheckerContext &C,
+                                                CallOrObjCMessage callOrMsg,
+                                                const char *BT_desc,
+                                                OwningPtr<BugType> &BT) {
+  // Don't check for uninitialized field values in arguments if the
+  // caller has a body that is available and we have the chance to inline it.
+  // This is a hack, but is a reasonable compromise betweens sometimes warning
+  // and sometimes not depending on if we decide to inline a function.
+  const Decl *D = callOrMsg.getDecl();
+  const bool checkUninitFields =
+    !(C.getAnalysisManager().shouldInlineCall() &&
+      (D && D->getBody()));
+  
+  for (unsigned i = 0, e = callOrMsg.getNumArgs(); i != e; ++i)
+    if (PreVisitProcessArg(C, callOrMsg.getArgSVal(i),
+                           callOrMsg.getArgSourceRange(i), callOrMsg.getArg(i),
+                           checkUninitFields,
+                           BT_desc, BT))
+      return;
+}
+
+bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
+                                               SVal V, SourceRange argRange,
+                                               const Expr *argEx,
+                                               const bool checkUninitFields,
+                                               const char *BT_desc,
+                                               OwningPtr<BugType> &BT) {
+  if (V.isUndef()) {
+    if (ExplodedNode *N = C.generateSink()) {
+      LazyInit_BT(BT_desc, BT);
+
+      // Generate a report for this bug.
+      BugReport *R = new BugReport(*BT, BT->getName(), N);
+      R->addRange(argRange);
+      if (argEx)
+        R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, argEx,
+                                                                   R));
+      C.EmitReport(R);
+    }
+    return true;
+  }
+
+  if (!checkUninitFields)
+    return false;
+  
+  if (const nonloc::LazyCompoundVal *LV =
+        dyn_cast<nonloc::LazyCompoundVal>(&V)) {
+
+    class FindUninitializedField {
+    public:
+      SmallVector<const FieldDecl *, 10> FieldChain;
+    private:
+      ASTContext &C;
+      StoreManager &StoreMgr;
+      MemRegionManager &MrMgr;
+      Store store;
+    public:
+      FindUninitializedField(ASTContext &c, StoreManager &storeMgr,
+                             MemRegionManager &mrMgr, Store s)
+      : C(c), StoreMgr(storeMgr), MrMgr(mrMgr), store(s) {}
+
+      bool Find(const TypedValueRegion *R) {
+        QualType T = R->getValueType();
+        if (const RecordType *RT = T->getAsStructureType()) {
+          const RecordDecl *RD = RT->getDecl()->getDefinition();
+          assert(RD && "Referred record has no definition");
+          for (RecordDecl::field_iterator I =
+               RD->field_begin(), E = RD->field_end(); I!=E; ++I) {
+            const FieldRegion *FR = MrMgr.getFieldRegion(*I, R);
+            FieldChain.push_back(*I);
+            T = (*I)->getType();
+            if (T->getAsStructureType()) {
+              if (Find(FR))
+                return true;
+            }
+            else {
+              const SVal &V = StoreMgr.getBinding(store, loc::MemRegionVal(FR));
+              if (V.isUndef())
+                return true;
+            }
+            FieldChain.pop_back();
+          }
+        }
+
+        return false;
+      }
+    };
+
+    const LazyCompoundValData *D = LV->getCVData();
+    FindUninitializedField F(C.getASTContext(),
+                             C.getState()->getStateManager().getStoreManager(),
+                             C.getSValBuilder().getRegionManager(),
+                             D->getStore());
+
+    if (F.Find(D->getRegion())) {
+      if (ExplodedNode *N = C.generateSink()) {
+        LazyInit_BT(BT_desc, BT);
+        SmallString<512> Str;
+        llvm::raw_svector_ostream os(Str);
+        os << "Passed-by-value struct argument contains uninitialized data";
+
+        if (F.FieldChain.size() == 1)
+          os << " (e.g., field: '" << *F.FieldChain[0] << "')";
+        else {
+          os << " (e.g., via the field chain: '";
+          bool first = true;
+          for (SmallVectorImpl<const FieldDecl *>::iterator
+               DI = F.FieldChain.begin(), DE = F.FieldChain.end(); DI!=DE;++DI){
+            if (first)
+              first = false;
+            else
+              os << '.';
+            os << **DI;
+          }
+          os << "')";
+        }
+
+        // Generate a report for this bug.
+        BugReport *R = new BugReport(*BT, os.str(), N);
+        R->addRange(argRange);
+
+        // FIXME: enhance track back for uninitialized value for arbitrary
+        // memregions
+        C.EmitReport(R);
+      }
+      return true;
+    }
+  }
+
+  return false;
+}
+
+void CallAndMessageChecker::checkPreStmt(const CallExpr *CE,
+                                         CheckerContext &C) const{
+
+  const Expr *Callee = CE->getCallee()->IgnoreParens();
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal L = C.getState()->getSVal(Callee, LCtx);
+
+  if (L.isUndef()) {
+    if (!BT_call_undef)
+      BT_call_undef.reset(new BuiltinBug("Called function pointer is an "
+                                         "uninitalized pointer value"));
+    EmitBadCall(BT_call_undef.get(), C, CE);
+    return;
+  }
+
+  if (isa<loc::ConcreteInt>(L)) {
+    if (!BT_call_null)
+      BT_call_null.reset(
+        new BuiltinBug("Called function pointer is null (null dereference)"));
+    EmitBadCall(BT_call_null.get(), C, CE);
+  }
+
+  PreVisitProcessArgs(C, CallOrObjCMessage(CE, C.getState(), LCtx),
+                      "Function call argument is an uninitialized value",
+                      BT_call_arg);
+}
+
+void CallAndMessageChecker::checkPreObjCMessage(ObjCMessage msg,
+                                                CheckerContext &C) const {
+
+  ProgramStateRef state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
+
+  // FIXME: Handle 'super'?
+  if (const Expr *receiver = msg.getInstanceReceiver()) {
+    SVal recVal = state->getSVal(receiver, LCtx);
+    if (recVal.isUndef()) {
+      if (ExplodedNode *N = C.generateSink()) {
+        BugType *BT = 0;
+        if (msg.isPureMessageExpr()) {
+          if (!BT_msg_undef)
+            BT_msg_undef.reset(new BuiltinBug("Receiver in message expression "
+                                              "is an uninitialized value"));
+          BT = BT_msg_undef.get();
+        }
+        else {
+          if (!BT_objc_prop_undef)
+            BT_objc_prop_undef.reset(new BuiltinBug("Property access on an "
+                                              "uninitialized object pointer"));
+          BT = BT_objc_prop_undef.get();
+        }
+        BugReport *R =
+          new BugReport(*BT, BT->getName(), N);
+        R->addRange(receiver->getSourceRange());
+        R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
+                                                                   receiver,
+                                                                   R));
+        C.EmitReport(R);
+      }
+      return;
+    } else {
+      // Bifurcate the state into nil and non-nil ones.
+      DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal);
+  
+      ProgramStateRef notNilState, nilState;
+      llvm::tie(notNilState, nilState) = state->assume(receiverVal);
+  
+      // Handle receiver must be nil.
+      if (nilState && !notNilState) {
+        HandleNilReceiver(C, state, msg);
+        return;
+      }
+    }
+  }
+
+  const char *bugDesc = msg.isPropertySetter() ?
+                     "Argument for property setter is an uninitialized value"
+                   : "Argument in message expression is an uninitialized value";
+  // Check for any arguments that are uninitialized/undefined.
+  PreVisitProcessArgs(C, CallOrObjCMessage(msg, state, LCtx),
+                      bugDesc, BT_msg_arg);
+}
+
+void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C,
+                                               const ObjCMessage &msg,
+                                               ExplodedNode *N) const {
+
+  if (!BT_msg_ret)
+    BT_msg_ret.reset(
+      new BuiltinBug("Receiver in message expression is "
+                     "'nil' and returns a garbage value"));
+
+  SmallString<200> buf;
+  llvm::raw_svector_ostream os(buf);
+  os << "The receiver of message '" << msg.getSelector().getAsString()
+     << "' is nil and returns a value of type '"
+     << msg.getType(C.getASTContext()).getAsString() << "' that will be garbage";
+
+  BugReport *report = new BugReport(*BT_msg_ret, os.str(), N);
+  if (const Expr *receiver = msg.getInstanceReceiver()) {
+    report->addRange(receiver->getSourceRange());
+    report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
+                                                                    receiver,
+                                                                    report));
+  }
+  C.EmitReport(report);
+}
+
+static bool supportsNilWithFloatRet(const llvm::Triple &triple) {
+  return (triple.getVendor() == llvm::Triple::Apple &&
+          (triple.getOS() == llvm::Triple::IOS ||
+           !triple.isMacOSXVersionLT(10,5)));
+}
+
+void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,
+                                              ProgramStateRef state,
+                                              ObjCMessage msg) const {
+  ASTContext &Ctx = C.getASTContext();
+
+  // Check the return type of the message expression.  A message to nil will
+  // return different values depending on the return type and the architecture.
+  QualType RetTy = msg.getType(Ctx);
+  CanQualType CanRetTy = Ctx.getCanonicalType(RetTy);
+  const LocationContext *LCtx = C.getLocationContext();
+
+  if (CanRetTy->isStructureOrClassType()) {
+    // Structure returns are safe since the compiler zeroes them out.
+    SVal V = C.getSValBuilder().makeZeroVal(msg.getType(Ctx));
+    C.addTransition(state->BindExpr(msg.getMessageExpr(), LCtx, V));
+    return;
+  }
+
+  // Other cases: check if sizeof(return type) > sizeof(void*)
+  if (CanRetTy != Ctx.VoidTy && C.getLocationContext()->getParentMap()
+                                  .isConsumedExpr(msg.getMessageExpr())) {
+    // Compute: sizeof(void *) and sizeof(return type)
+    const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy);
+    const uint64_t returnTypeSize = Ctx.getTypeSize(CanRetTy);
+
+    if (voidPtrSize < returnTypeSize &&
+        !(supportsNilWithFloatRet(Ctx.getTargetInfo().getTriple()) &&
+          (Ctx.FloatTy == CanRetTy ||
+           Ctx.DoubleTy == CanRetTy ||
+           Ctx.LongDoubleTy == CanRetTy ||
+           Ctx.LongLongTy == CanRetTy ||
+           Ctx.UnsignedLongLongTy == CanRetTy))) {
+      if (ExplodedNode *N = C.generateSink(state))
+        emitNilReceiverBug(C, msg, N);
+      return;
+    }
+
+    // Handle the safe cases where the return value is 0 if the
+    // receiver is nil.
+    //
+    // FIXME: For now take the conservative approach that we only
+    // return null values if we *know* that the receiver is nil.
+    // This is because we can have surprises like:
+    //
+    //   ... = [[NSScreens screens] objectAtIndex:0];
+    //
+    // What can happen is that [... screens] could return nil, but
+    // it most likely isn't nil.  We should assume the semantics
+    // of this case unless we have *a lot* more knowledge.
+    //
+    SVal V = C.getSValBuilder().makeZeroVal(msg.getType(Ctx));
+    C.addTransition(state->BindExpr(msg.getMessageExpr(), LCtx, V));
+    return;
+  }
+
+  C.addTransition(state);
+}
+
+void ento::registerCallAndMessageChecker(CheckerManager &mgr) {
+  mgr.registerChecker<CallAndMessageChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
new file mode 100644
index 0000000..2e184fb
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
@@ -0,0 +1,86 @@
+//=== CastSizeChecker.cpp ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// CastSizeChecker checks when casting a malloc'ed symbolic region to type T,
+// whether the size of the symbolic region is a multiple of the size of T.
+//
+//===----------------------------------------------------------------------===//
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/AST/CharUnits.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class CastSizeChecker : public Checker< check::PreStmt<CastExpr> > {
+  mutable OwningPtr<BuiltinBug> BT;
+public:
+  void checkPreStmt(const CastExpr *CE, CheckerContext &C) const;
+};
+}
+
+void CastSizeChecker::checkPreStmt(const CastExpr *CE,CheckerContext &C) const {
+  const Expr *E = CE->getSubExpr();
+  ASTContext &Ctx = C.getASTContext();
+  QualType ToTy = Ctx.getCanonicalType(CE->getType());
+  const PointerType *ToPTy = dyn_cast<PointerType>(ToTy.getTypePtr());
+
+  if (!ToPTy)
+    return;
+
+  QualType ToPointeeTy = ToPTy->getPointeeType();
+
+  // Only perform the check if 'ToPointeeTy' is a complete type.
+  if (ToPointeeTy->isIncompleteType())
+    return;
+
+  ProgramStateRef state = C.getState();
+  const MemRegion *R = state->getSVal(E, C.getLocationContext()).getAsRegion();
+  if (R == 0)
+    return;
+
+  const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R);
+  if (SR == 0)
+    return;
+
+  SValBuilder &svalBuilder = C.getSValBuilder();
+  SVal extent = SR->getExtent(svalBuilder);
+  const llvm::APSInt *extentInt = svalBuilder.getKnownValue(state, extent);
+  if (!extentInt)
+    return;
+
+  CharUnits regionSize = CharUnits::fromQuantity(extentInt->getSExtValue());
+  CharUnits typeSize = C.getASTContext().getTypeSizeInChars(ToPointeeTy);
+
+  // Ignore void, and a few other un-sizeable types.
+  if (typeSize.isZero())
+    return;
+
+  if (regionSize % typeSize != 0) {
+    if (ExplodedNode *errorNode = C.generateSink()) {
+      if (!BT)
+        BT.reset(new BuiltinBug("Cast region with wrong size.",
+                            "Cast a region whose size is not a multiple of the"
+                            " destination type size."));
+      BugReport *R = new BugReport(*BT, BT->getDescription(),
+                                               errorNode);
+      R->addRange(CE->getSourceRange());
+      C.EmitReport(R);
+    }
+  }
+}
+
+
+void ento::registerCastSizeChecker(CheckerManager &mgr) {
+  mgr.registerChecker<CastSizeChecker>();  
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
new file mode 100644
index 0000000..1407638
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
@@ -0,0 +1,74 @@
+//=== CastToStructChecker.cpp - Fixed address usage checker ----*- C++ -*--===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This files defines CastToStructChecker, a builtin checker that checks for
+// cast from non-struct pointer to struct pointer.
+// This check corresponds to CWE-588.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class CastToStructChecker : public Checker< check::PreStmt<CastExpr> > {
+  mutable OwningPtr<BuiltinBug> BT;
+
+public:
+  void checkPreStmt(const CastExpr *CE, CheckerContext &C) const;
+};
+}
+
+void CastToStructChecker::checkPreStmt(const CastExpr *CE,
+                                       CheckerContext &C) const {
+  const Expr *E = CE->getSubExpr();
+  ASTContext &Ctx = C.getASTContext();
+  QualType OrigTy = Ctx.getCanonicalType(E->getType());
+  QualType ToTy = Ctx.getCanonicalType(CE->getType());
+
+  const PointerType *OrigPTy = dyn_cast<PointerType>(OrigTy.getTypePtr());
+  const PointerType *ToPTy = dyn_cast<PointerType>(ToTy.getTypePtr());
+
+  if (!ToPTy || !OrigPTy)
+    return;
+
+  QualType OrigPointeeTy = OrigPTy->getPointeeType();
+  QualType ToPointeeTy = ToPTy->getPointeeType();
+
+  if (!ToPointeeTy->isStructureOrClassType())
+    return;
+
+  // We allow cast from void*.
+  if (OrigPointeeTy->isVoidType())
+    return;
+
+  // Now the cast-to-type is struct pointer, the original type is not void*.
+  if (!OrigPointeeTy->isRecordType()) {
+    if (ExplodedNode *N = C.addTransition()) {
+      if (!BT)
+        BT.reset(new BuiltinBug("Cast from non-struct type to struct type",
+                            "Casting a non-structure type to a structure type "
+                            "and accessing a field can lead to memory access "
+                            "errors or data corruption."));
+      BugReport *R = new BugReport(*BT,BT->getDescription(), N);
+      R->addRange(CE->getSourceRange());
+      C.EmitReport(R);
+    }
+  }
+}
+
+void ento::registerCastToStructChecker(CheckerManager &mgr) {
+  mgr.registerChecker<CastToStructChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp b/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
new file mode 100644
index 0000000..133204a
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
@@ -0,0 +1,291 @@
+//==- CheckObjCDealloc.cpp - Check ObjC -dealloc implementation --*- 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 CheckObjCDealloc, a checker that
+//  analyzes an Objective-C class's implementation to determine if it
+//  correctly implements -dealloc.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/LangOptions.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace ento;
+
+static bool scan_dealloc(Stmt *S, Selector Dealloc) {
+
+  if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S))
+    if (ME->getSelector() == Dealloc) {
+      switch (ME->getReceiverKind()) {
+      case ObjCMessageExpr::Instance: return false;
+      case ObjCMessageExpr::SuperInstance: return true;
+      case ObjCMessageExpr::Class: break;
+      case ObjCMessageExpr::SuperClass: break;
+      }
+    }
+
+  // Recurse to children.
+
+  for (Stmt::child_iterator I = S->child_begin(), E= S->child_end(); I!=E; ++I)
+    if (*I && scan_dealloc(*I, Dealloc))
+      return true;
+
+  return false;
+}
+
+static bool scan_ivar_release(Stmt *S, ObjCIvarDecl *ID,
+                              const ObjCPropertyDecl *PD,
+                              Selector Release,
+                              IdentifierInfo* SelfII,
+                              ASTContext &Ctx) {
+
+  // [mMyIvar release]
+  if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S))
+    if (ME->getSelector() == Release)
+      if (ME->getInstanceReceiver())
+        if (Expr *Receiver = ME->getInstanceReceiver()->IgnoreParenCasts())
+          if (ObjCIvarRefExpr *E = dyn_cast<ObjCIvarRefExpr>(Receiver))
+            if (E->getDecl() == ID)
+              return true;
+
+  // [self setMyIvar:nil];
+  if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S))
+    if (ME->getInstanceReceiver())
+      if (Expr *Receiver = ME->getInstanceReceiver()->IgnoreParenCasts())
+        if (DeclRefExpr *E = dyn_cast<DeclRefExpr>(Receiver))
+          if (E->getDecl()->getIdentifier() == SelfII)
+            if (ME->getMethodDecl() == PD->getSetterMethodDecl() &&
+                ME->getNumArgs() == 1 &&
+                ME->getArg(0)->isNullPointerConstant(Ctx, 
+                                              Expr::NPC_ValueDependentIsNull))
+              return true;
+
+  // self.myIvar = nil;
+  if (BinaryOperator* BO = dyn_cast<BinaryOperator>(S))
+    if (BO->isAssignmentOp())
+      if (ObjCPropertyRefExpr *PRE =
+           dyn_cast<ObjCPropertyRefExpr>(BO->getLHS()->IgnoreParenCasts()))
+        if (PRE->isExplicitProperty() && PRE->getExplicitProperty() == PD)
+            if (BO->getRHS()->isNullPointerConstant(Ctx, 
+                                            Expr::NPC_ValueDependentIsNull)) {
+              // This is only a 'release' if the property kind is not
+              // 'assign'.
+              return PD->getSetterKind() != ObjCPropertyDecl::Assign;;
+            }
+
+  // Recurse to children.
+  for (Stmt::child_iterator I = S->child_begin(), E= S->child_end(); I!=E; ++I)
+    if (*I && scan_ivar_release(*I, ID, PD, Release, SelfII, Ctx))
+      return true;
+
+  return false;
+}
+
+static void checkObjCDealloc(const ObjCImplementationDecl *D,
+                             const LangOptions& LOpts, BugReporter& BR) {
+
+  assert (LOpts.getGC() != LangOptions::GCOnly);
+
+  ASTContext &Ctx = BR.getContext();
+  const ObjCInterfaceDecl *ID = D->getClassInterface();
+
+  // Does the class contain any ivars that are pointers (or id<...>)?
+  // If not, skip the check entirely.
+  // NOTE: This is motivated by PR 2517:
+  //        http://llvm.org/bugs/show_bug.cgi?id=2517
+
+  bool containsPointerIvar = false;
+
+  for (ObjCInterfaceDecl::ivar_iterator I=ID->ivar_begin(), E=ID->ivar_end();
+       I!=E; ++I) {
+
+    ObjCIvarDecl *ID = *I;
+    QualType T = ID->getType();
+
+    if (!T->isObjCObjectPointerType() ||
+        ID->getAttr<IBOutletAttr>() || // Skip IBOutlets.
+        ID->getAttr<IBOutletCollectionAttr>()) // Skip IBOutletCollections.
+      continue;
+
+    containsPointerIvar = true;
+    break;
+  }
+
+  if (!containsPointerIvar)
+    return;
+
+  // Determine if the class subclasses NSObject.
+  IdentifierInfo* NSObjectII = &Ctx.Idents.get("NSObject");
+  IdentifierInfo* SenTestCaseII = &Ctx.Idents.get("SenTestCase");
+
+
+  for ( ; ID ; ID = ID->getSuperClass()) {
+    IdentifierInfo *II = ID->getIdentifier();
+
+    if (II == NSObjectII)
+      break;
+
+    // FIXME: For now, ignore classes that subclass SenTestCase, as these don't
+    // need to implement -dealloc.  They implement tear down in another way,
+    // which we should try and catch later.
+    //  http://llvm.org/bugs/show_bug.cgi?id=3187
+    if (II == SenTestCaseII)
+      return;
+  }
+
+  if (!ID)
+    return;
+
+  // Get the "dealloc" selector.
+  IdentifierInfo* II = &Ctx.Idents.get("dealloc");
+  Selector S = Ctx.Selectors.getSelector(0, &II);
+  ObjCMethodDecl *MD = 0;
+
+  // Scan the instance methods for "dealloc".
+  for (ObjCImplementationDecl::instmeth_iterator I = D->instmeth_begin(),
+       E = D->instmeth_end(); I!=E; ++I) {
+
+    if ((*I)->getSelector() == S) {
+      MD = *I;
+      break;
+    }
+  }
+
+  PathDiagnosticLocation DLoc =
+    PathDiagnosticLocation::createBegin(D, BR.getSourceManager());
+
+  if (!MD) { // No dealloc found.
+
+    const char* name = LOpts.getGC() == LangOptions::NonGC
+                       ? "missing -dealloc"
+                       : "missing -dealloc (Hybrid MM, non-GC)";
+
+    std::string buf;
+    llvm::raw_string_ostream os(buf);
+    os << "Objective-C class '" << *D << "' lacks a 'dealloc' instance method";
+
+    BR.EmitBasicReport(D, name, categories::CoreFoundationObjectiveC,
+                       os.str(), DLoc);
+    return;
+  }
+
+  // dealloc found.  Scan for missing [super dealloc].
+  if (MD->getBody() && !scan_dealloc(MD->getBody(), S)) {
+
+    const char* name = LOpts.getGC() == LangOptions::NonGC
+                       ? "missing [super dealloc]"
+                       : "missing [super dealloc] (Hybrid MM, non-GC)";
+
+    std::string buf;
+    llvm::raw_string_ostream os(buf);
+    os << "The 'dealloc' instance method in Objective-C class '" << *D
+       << "' does not send a 'dealloc' message to its super class"
+           " (missing [super dealloc])";
+
+    BR.EmitBasicReport(MD, name, categories::CoreFoundationObjectiveC,
+                       os.str(), DLoc);
+    return;
+  }
+
+  // Get the "release" selector.
+  IdentifierInfo* RII = &Ctx.Idents.get("release");
+  Selector RS = Ctx.Selectors.getSelector(0, &RII);
+
+  // Get the "self" identifier
+  IdentifierInfo* SelfII = &Ctx.Idents.get("self");
+
+  // Scan for missing and extra releases of ivars used by implementations
+  // of synthesized properties
+  for (ObjCImplementationDecl::propimpl_iterator I = D->propimpl_begin(),
+       E = D->propimpl_end(); I!=E; ++I) {
+
+    // We can only check the synthesized properties
+    if ((*I)->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize)
+      continue;
+
+    ObjCIvarDecl *ID = (*I)->getPropertyIvarDecl();
+    if (!ID)
+      continue;
+
+    QualType T = ID->getType();
+    if (!T->isObjCObjectPointerType()) // Skip non-pointer ivars
+      continue;
+
+    const ObjCPropertyDecl *PD = (*I)->getPropertyDecl();
+    if (!PD)
+      continue;
+
+    // ivars cannot be set via read-only properties, so we'll skip them
+    if (PD->isReadOnly())
+      continue;
+
+    // ivar must be released if and only if the kind of setter was not 'assign'
+    bool requiresRelease = PD->getSetterKind() != ObjCPropertyDecl::Assign;
+    if (scan_ivar_release(MD->getBody(), ID, PD, RS, SelfII, Ctx)
+       != requiresRelease) {
+      const char *name = 0;
+      std::string buf;
+      llvm::raw_string_ostream os(buf);
+
+      if (requiresRelease) {
+        name = LOpts.getGC() == LangOptions::NonGC
+               ? "missing ivar release (leak)"
+               : "missing ivar release (Hybrid MM, non-GC)";
+
+        os << "The '" << *ID
+           << "' instance variable was retained by a synthesized property but "
+              "wasn't released in 'dealloc'";
+      } else {
+        name = LOpts.getGC() == LangOptions::NonGC
+               ? "extra ivar release (use-after-release)"
+               : "extra ivar release (Hybrid MM, non-GC)";
+
+        os << "The '" << *ID
+           << "' instance variable was not retained by a synthesized property "
+              "but was released in 'dealloc'";
+      }
+
+      PathDiagnosticLocation SDLoc =
+        PathDiagnosticLocation::createBegin((*I), BR.getSourceManager());
+
+      BR.EmitBasicReport(MD, name, categories::CoreFoundationObjectiveC,
+                         os.str(), SDLoc);
+    }
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// ObjCDeallocChecker
+//===----------------------------------------------------------------------===//
+
+namespace {
+class ObjCDeallocChecker : public Checker<
+                                      check::ASTDecl<ObjCImplementationDecl> > {
+public:
+  void checkASTDecl(const ObjCImplementationDecl *D, AnalysisManager& mgr,
+                    BugReporter &BR) const {
+    if (mgr.getLangOpts().getGC() == LangOptions::GCOnly)
+      return;
+    checkObjCDealloc(cast<ObjCImplementationDecl>(D), mgr.getLangOpts(), BR);
+  }
+};
+}
+
+void ento::registerObjCDeallocChecker(CheckerManager &mgr) {
+  mgr.registerChecker<ObjCDeallocChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/CheckObjCInstMethSignature.cpp b/clang/lib/StaticAnalyzer/Checkers/CheckObjCInstMethSignature.cpp
new file mode 100644
index 0000000..6df47b1
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/CheckObjCInstMethSignature.cpp
@@ -0,0 +1,146 @@
+//=- CheckObjCInstMethodRetTy.cpp - Check ObjC method signatures -*- 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 CheckObjCInstMethSignature, a flow-insenstive check
+//  that determines if an Objective-C class interface incorrectly redefines
+//  the method signature in a subclass.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/ASTContext.h"
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace ento;
+
+static bool AreTypesCompatible(QualType Derived, QualType Ancestor,
+                               ASTContext &C) {
+
+  // Right now don't compare the compatibility of pointers.  That involves
+  // looking at subtyping relationships.  FIXME: Future patch.
+  if (Derived->isAnyPointerType() &&  Ancestor->isAnyPointerType())
+    return true;
+
+  return C.typesAreCompatible(Derived, Ancestor);
+}
+
+static void CompareReturnTypes(const ObjCMethodDecl *MethDerived,
+                               const ObjCMethodDecl *MethAncestor,
+                               BugReporter &BR, ASTContext &Ctx,
+                               const ObjCImplementationDecl *ID) {
+
+  QualType ResDerived  = MethDerived->getResultType();
+  QualType ResAncestor = MethAncestor->getResultType();
+
+  if (!AreTypesCompatible(ResDerived, ResAncestor, Ctx)) {
+    std::string sbuf;
+    llvm::raw_string_ostream os(sbuf);
+
+    os << "The Objective-C class '"
+       << *MethDerived->getClassInterface()
+       << "', which is derived from class '"
+       << *MethAncestor->getClassInterface()
+       << "', defines the instance method '"
+       << MethDerived->getSelector().getAsString()
+       << "' whose return type is '"
+       << ResDerived.getAsString()
+       << "'.  A method with the same name (same selector) is also defined in "
+          "class '"
+       << *MethAncestor->getClassInterface()
+       << "' and has a return type of '"
+       << ResAncestor.getAsString()
+       << "'.  These two types are incompatible, and may result in undefined "
+          "behavior for clients of these classes.";
+
+    PathDiagnosticLocation MethDLoc =
+      PathDiagnosticLocation::createBegin(MethDerived,
+                                          BR.getSourceManager());
+
+    BR.EmitBasicReport(MethDerived,
+                       "Incompatible instance method return type",
+                       categories::CoreFoundationObjectiveC,
+                       os.str(), MethDLoc);
+  }
+}
+
+static void CheckObjCInstMethSignature(const ObjCImplementationDecl *ID,
+                                       BugReporter& BR) {
+
+  const ObjCInterfaceDecl *D = ID->getClassInterface();
+  const ObjCInterfaceDecl *C = D->getSuperClass();
+
+  if (!C)
+    return;
+
+  ASTContext &Ctx = BR.getContext();
+
+  // Build a DenseMap of the methods for quick querying.
+  typedef llvm::DenseMap<Selector,ObjCMethodDecl*> MapTy;
+  MapTy IMeths;
+  unsigned NumMethods = 0;
+
+  for (ObjCImplementationDecl::instmeth_iterator I=ID->instmeth_begin(),
+       E=ID->instmeth_end(); I!=E; ++I) {
+
+    ObjCMethodDecl *M = *I;
+    IMeths[M->getSelector()] = M;
+    ++NumMethods;
+  }
+
+  // Now recurse the class hierarchy chain looking for methods with the
+  // same signatures.
+  while (C && NumMethods) {
+    for (ObjCInterfaceDecl::instmeth_iterator I=C->instmeth_begin(),
+         E=C->instmeth_end(); I!=E; ++I) {
+
+      ObjCMethodDecl *M = *I;
+      Selector S = M->getSelector();
+
+      MapTy::iterator MI = IMeths.find(S);
+
+      if (MI == IMeths.end() || MI->second == 0)
+        continue;
+
+      --NumMethods;
+      ObjCMethodDecl *MethDerived = MI->second;
+      MI->second = 0;
+
+      CompareReturnTypes(MethDerived, M, BR, Ctx, ID);
+    }
+
+    C = C->getSuperClass();
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// ObjCMethSigsChecker
+//===----------------------------------------------------------------------===//
+
+namespace {
+class ObjCMethSigsChecker : public Checker<
+                                      check::ASTDecl<ObjCImplementationDecl> > {
+public:
+  void checkASTDecl(const ObjCImplementationDecl *D, AnalysisManager& mgr,
+                    BugReporter &BR) const {
+    CheckObjCInstMethSignature(D, BR);
+  }
+};
+}
+
+void ento::registerObjCMethSigsChecker(CheckerManager &mgr) {
+  mgr.registerChecker<ObjCMethSigsChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp b/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
new file mode 100644
index 0000000..dde9071
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
@@ -0,0 +1,786 @@
+//==- CheckSecuritySyntaxOnly.cpp - Basic security checks --------*- 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 set of flow-insensitive security checks.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace ento;
+
+static bool isArc4RandomAvailable(const ASTContext &Ctx) {
+  const llvm::Triple &T = Ctx.getTargetInfo().getTriple();
+  return T.getVendor() == llvm::Triple::Apple ||
+         T.getOS() == llvm::Triple::FreeBSD ||
+         T.getOS() == llvm::Triple::NetBSD ||
+         T.getOS() == llvm::Triple::OpenBSD ||
+         T.getOS() == llvm::Triple::DragonFly;
+}
+
+namespace {
+struct DefaultBool {
+  bool val;
+  DefaultBool() : val(false) {}
+  operator bool() const { return val; }
+  DefaultBool &operator=(bool b) { val = b; return *this; }
+};
+  
+struct ChecksFilter {
+  DefaultBool check_gets;
+  DefaultBool check_getpw;
+  DefaultBool check_mktemp;
+  DefaultBool check_mkstemp;
+  DefaultBool check_strcpy;
+  DefaultBool check_rand;
+  DefaultBool check_vfork;
+  DefaultBool check_FloatLoopCounter;
+  DefaultBool check_UncheckedReturn;
+};
+  
+class WalkAST : public StmtVisitor<WalkAST> {
+  BugReporter &BR;
+  AnalysisDeclContext* AC;
+  enum { num_setids = 6 };
+  IdentifierInfo *II_setid[num_setids];
+
+  const bool CheckRand;
+  const ChecksFilter &filter;
+
+public:
+  WalkAST(BugReporter &br, AnalysisDeclContext* ac,
+          const ChecksFilter &f)
+  : BR(br), AC(ac), II_setid(),
+    CheckRand(isArc4RandomAvailable(BR.getContext())),
+    filter(f) {}
+
+  // Statement visitor methods.
+  void VisitCallExpr(CallExpr *CE);
+  void VisitForStmt(ForStmt *S);
+  void VisitCompoundStmt (CompoundStmt *S);
+  void VisitStmt(Stmt *S) { VisitChildren(S); }
+
+  void VisitChildren(Stmt *S);
+
+  // Helpers.
+  bool checkCall_strCommon(const CallExpr *CE, const FunctionDecl *FD);
+
+  typedef void (WalkAST::*FnCheck)(const CallExpr *,
+				   const FunctionDecl *);
+
+  // Checker-specific methods.
+  void checkLoopConditionForFloat(const ForStmt *FS);
+  void checkCall_gets(const CallExpr *CE, const FunctionDecl *FD);
+  void checkCall_getpw(const CallExpr *CE, const FunctionDecl *FD);
+  void checkCall_mktemp(const CallExpr *CE, const FunctionDecl *FD);
+  void checkCall_mkstemp(const CallExpr *CE, const FunctionDecl *FD);
+  void checkCall_strcpy(const CallExpr *CE, const FunctionDecl *FD);
+  void checkCall_strcat(const CallExpr *CE, const FunctionDecl *FD);
+  void checkCall_rand(const CallExpr *CE, const FunctionDecl *FD);
+  void checkCall_random(const CallExpr *CE, const FunctionDecl *FD);
+  void checkCall_vfork(const CallExpr *CE, const FunctionDecl *FD);
+  void checkUncheckedReturnValue(CallExpr *CE);
+};
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// AST walking.
+//===----------------------------------------------------------------------===//
+
+void WalkAST::VisitChildren(Stmt *S) {
+  for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
+    if (Stmt *child = *I)
+      Visit(child);
+}
+
+void WalkAST::VisitCallExpr(CallExpr *CE) {
+  // Get the callee.  
+  const FunctionDecl *FD = CE->getDirectCallee();
+
+  if (!FD)
+    return;
+
+  // Get the name of the callee. If it's a builtin, strip off the prefix.
+  IdentifierInfo *II = FD->getIdentifier();
+  if (!II)   // if no identifier, not a simple C function
+    return;
+  StringRef Name = II->getName();
+  if (Name.startswith("__builtin_"))
+    Name = Name.substr(10);
+
+  // Set the evaluation function by switching on the callee name.
+  FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
+    .Case("gets", &WalkAST::checkCall_gets)
+    .Case("getpw", &WalkAST::checkCall_getpw)
+    .Case("mktemp", &WalkAST::checkCall_mktemp)
+    .Case("mkstemp", &WalkAST::checkCall_mkstemp)
+    .Case("mkdtemp", &WalkAST::checkCall_mkstemp)
+    .Case("mkstemps", &WalkAST::checkCall_mkstemp)
+    .Cases("strcpy", "__strcpy_chk", &WalkAST::checkCall_strcpy)
+    .Cases("strcat", "__strcat_chk", &WalkAST::checkCall_strcat)
+    .Case("drand48", &WalkAST::checkCall_rand)
+    .Case("erand48", &WalkAST::checkCall_rand)
+    .Case("jrand48", &WalkAST::checkCall_rand)
+    .Case("lrand48", &WalkAST::checkCall_rand)
+    .Case("mrand48", &WalkAST::checkCall_rand)
+    .Case("nrand48", &WalkAST::checkCall_rand)
+    .Case("lcong48", &WalkAST::checkCall_rand)
+    .Case("rand", &WalkAST::checkCall_rand)
+    .Case("rand_r", &WalkAST::checkCall_rand)
+    .Case("random", &WalkAST::checkCall_random)
+    .Case("vfork", &WalkAST::checkCall_vfork)
+    .Default(NULL);
+
+  // If the callee isn't defined, it is not of security concern.
+  // Check and evaluate the call.
+  if (evalFunction)
+    (this->*evalFunction)(CE, FD);
+
+  // Recurse and check children.
+  VisitChildren(CE);
+}
+
+void WalkAST::VisitCompoundStmt(CompoundStmt *S) {
+  for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
+    if (Stmt *child = *I) {
+      if (CallExpr *CE = dyn_cast<CallExpr>(child))
+        checkUncheckedReturnValue(CE);
+      Visit(child);
+    }
+}
+
+void WalkAST::VisitForStmt(ForStmt *FS) {
+  checkLoopConditionForFloat(FS);
+
+  // Recurse and check children.
+  VisitChildren(FS);
+}
+
+//===----------------------------------------------------------------------===//
+// Check: floating poing variable used as loop counter.
+// Originally: <rdar://problem/6336718>
+// Implements: CERT security coding advisory FLP-30.
+//===----------------------------------------------------------------------===//
+
+static const DeclRefExpr*
+getIncrementedVar(const Expr *expr, const VarDecl *x, const VarDecl *y) {
+  expr = expr->IgnoreParenCasts();
+
+  if (const BinaryOperator *B = dyn_cast<BinaryOperator>(expr)) {
+    if (!(B->isAssignmentOp() || B->isCompoundAssignmentOp() ||
+          B->getOpcode() == BO_Comma))
+      return NULL;
+
+    if (const DeclRefExpr *lhs = getIncrementedVar(B->getLHS(), x, y))
+      return lhs;
+
+    if (const DeclRefExpr *rhs = getIncrementedVar(B->getRHS(), x, y))
+      return rhs;
+
+    return NULL;
+  }
+
+  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(expr)) {
+    const NamedDecl *ND = DR->getDecl();
+    return ND == x || ND == y ? DR : NULL;
+  }
+
+  if (const UnaryOperator *U = dyn_cast<UnaryOperator>(expr))
+    return U->isIncrementDecrementOp()
+      ? getIncrementedVar(U->getSubExpr(), x, y) : NULL;
+
+  return NULL;
+}
+
+/// CheckLoopConditionForFloat - This check looks for 'for' statements that
+///  use a floating point variable as a loop counter.
+///  CERT: FLP30-C, FLP30-CPP.
+///
+void WalkAST::checkLoopConditionForFloat(const ForStmt *FS) {
+  if (!filter.check_FloatLoopCounter)
+    return;
+
+  // Does the loop have a condition?
+  const Expr *condition = FS->getCond();
+
+  if (!condition)
+    return;
+
+  // Does the loop have an increment?
+  const Expr *increment = FS->getInc();
+
+  if (!increment)
+    return;
+
+  // Strip away '()' and casts.
+  condition = condition->IgnoreParenCasts();
+  increment = increment->IgnoreParenCasts();
+
+  // Is the loop condition a comparison?
+  const BinaryOperator *B = dyn_cast<BinaryOperator>(condition);
+
+  if (!B)
+    return;
+
+  // Is this a comparison?
+  if (!(B->isRelationalOp() || B->isEqualityOp()))
+    return;
+
+  // Are we comparing variables?
+  const DeclRefExpr *drLHS =
+    dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParenLValueCasts());
+  const DeclRefExpr *drRHS =
+    dyn_cast<DeclRefExpr>(B->getRHS()->IgnoreParenLValueCasts());
+
+  // Does at least one of the variables have a floating point type?
+  drLHS = drLHS && drLHS->getType()->isRealFloatingType() ? drLHS : NULL;
+  drRHS = drRHS && drRHS->getType()->isRealFloatingType() ? drRHS : NULL;
+
+  if (!drLHS && !drRHS)
+    return;
+
+  const VarDecl *vdLHS = drLHS ? dyn_cast<VarDecl>(drLHS->getDecl()) : NULL;
+  const VarDecl *vdRHS = drRHS ? dyn_cast<VarDecl>(drRHS->getDecl()) : NULL;
+
+  if (!vdLHS && !vdRHS)
+    return;
+
+  // Does either variable appear in increment?
+  const DeclRefExpr *drInc = getIncrementedVar(increment, vdLHS, vdRHS);
+
+  if (!drInc)
+    return;
+
+  // Emit the error.  First figure out which DeclRefExpr in the condition
+  // referenced the compared variable.
+  const DeclRefExpr *drCond = vdLHS == drInc->getDecl() ? drLHS : drRHS;
+
+  SmallVector<SourceRange, 2> ranges;
+  SmallString<256> sbuf;
+  llvm::raw_svector_ostream os(sbuf);
+
+  os << "Variable '" << drCond->getDecl()->getName()
+     << "' with floating point type '" << drCond->getType().getAsString()
+     << "' should not be used as a loop counter";
+
+  ranges.push_back(drCond->getSourceRange());
+  ranges.push_back(drInc->getSourceRange());
+
+  const char *bugType = "Floating point variable used as loop counter";
+
+  PathDiagnosticLocation FSLoc =
+    PathDiagnosticLocation::createBegin(FS, BR.getSourceManager(), AC);
+  BR.EmitBasicReport(AC->getDecl(),
+                     bugType, "Security", os.str(),
+                     FSLoc, ranges.data(), ranges.size());
+}
+
+//===----------------------------------------------------------------------===//
+// Check: Any use of 'gets' is insecure.
+// Originally: <rdar://problem/6335715>
+// Implements (part of): 300-BSI (buildsecurityin.us-cert.gov)
+// CWE-242: Use of Inherently Dangerous Function
+//===----------------------------------------------------------------------===//
+
+void WalkAST::checkCall_gets(const CallExpr *CE, const FunctionDecl *FD) {
+  if (!filter.check_gets)
+    return;
+  
+  const FunctionProtoType *FPT
+    = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
+  if (!FPT)
+    return;
+
+  // Verify that the function takes a single argument.
+  if (FPT->getNumArgs() != 1)
+    return;
+
+  // Is the argument a 'char*'?
+  const PointerType *PT = dyn_cast<PointerType>(FPT->getArgType(0));
+  if (!PT)
+    return;
+
+  if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
+    return;
+
+  // Issue a warning.
+  SourceRange R = CE->getCallee()->getSourceRange();
+  PathDiagnosticLocation CELoc =
+    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
+  BR.EmitBasicReport(AC->getDecl(),
+                     "Potential buffer overflow in call to 'gets'",
+                     "Security",
+                     "Call to function 'gets' is extremely insecure as it can "
+                     "always result in a buffer overflow",
+                     CELoc, &R, 1);
+}
+
+//===----------------------------------------------------------------------===//
+// Check: Any use of 'getpwd' is insecure.
+// CWE-477: Use of Obsolete Functions
+//===----------------------------------------------------------------------===//
+
+void WalkAST::checkCall_getpw(const CallExpr *CE, const FunctionDecl *FD) {
+  if (!filter.check_getpw)
+    return;
+
+  const FunctionProtoType *FPT
+    = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
+  if (!FPT)
+    return;
+
+  // Verify that the function takes two arguments.
+  if (FPT->getNumArgs() != 2)
+    return;
+
+  // Verify the first argument type is integer.
+  if (!FPT->getArgType(0)->isIntegerType())
+    return;
+
+  // Verify the second argument type is char*.
+  const PointerType *PT = dyn_cast<PointerType>(FPT->getArgType(1));
+  if (!PT)
+    return;
+
+  if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
+    return;
+
+  // Issue a warning.
+  SourceRange R = CE->getCallee()->getSourceRange();
+  PathDiagnosticLocation CELoc =
+    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
+  BR.EmitBasicReport(AC->getDecl(),
+                     "Potential buffer overflow in call to 'getpw'",
+                     "Security",
+                     "The getpw() function is dangerous as it may overflow the "
+                     "provided buffer. It is obsoleted by getpwuid().",
+                     CELoc, &R, 1);
+}
+
+//===----------------------------------------------------------------------===//
+// Check: Any use of 'mktemp' is insecure.  It is obsoleted by mkstemp().
+// CWE-377: Insecure Temporary File
+//===----------------------------------------------------------------------===//
+
+void WalkAST::checkCall_mktemp(const CallExpr *CE, const FunctionDecl *FD) {
+  if (!filter.check_mktemp) {
+    // Fall back to the security check of looking for enough 'X's in the
+    // format string, since that is a less severe warning.
+    checkCall_mkstemp(CE, FD);
+    return;
+  }
+
+  const FunctionProtoType *FPT
+    = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
+  if(!FPT)
+    return;
+
+  // Verify that the function takes a single argument.
+  if (FPT->getNumArgs() != 1)
+    return;
+
+  // Verify that the argument is Pointer Type.
+  const PointerType *PT = dyn_cast<PointerType>(FPT->getArgType(0));
+  if (!PT)
+    return;
+
+  // Verify that the argument is a 'char*'.
+  if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
+    return;
+
+  // Issue a waring.
+  SourceRange R = CE->getCallee()->getSourceRange();
+  PathDiagnosticLocation CELoc =
+    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
+  BR.EmitBasicReport(AC->getDecl(),
+                     "Potential insecure temporary file in call 'mktemp'",
+                     "Security",
+                     "Call to function 'mktemp' is insecure as it always "
+                     "creates or uses insecure temporary file.  Use 'mkstemp' "
+                     "instead",
+                     CELoc, &R, 1);
+}
+
+
+//===----------------------------------------------------------------------===//
+// Check: Use of 'mkstemp', 'mktemp', 'mkdtemp' should contain at least 6 X's.
+//===----------------------------------------------------------------------===//
+
+void WalkAST::checkCall_mkstemp(const CallExpr *CE, const FunctionDecl *FD) {
+  if (!filter.check_mkstemp)
+    return;
+
+  StringRef Name = FD->getIdentifier()->getName();
+  std::pair<signed, signed> ArgSuffix =
+    llvm::StringSwitch<std::pair<signed, signed> >(Name)
+      .Case("mktemp", std::make_pair(0,-1))
+      .Case("mkstemp", std::make_pair(0,-1))
+      .Case("mkdtemp", std::make_pair(0,-1))
+      .Case("mkstemps", std::make_pair(0,1))
+      .Default(std::make_pair(-1, -1));
+  
+  assert(ArgSuffix.first >= 0 && "Unsupported function");
+
+  // Check if the number of arguments is consistent with out expectations.
+  unsigned numArgs = CE->getNumArgs();
+  if ((signed) numArgs <= ArgSuffix.first)
+    return;
+  
+  const StringLiteral *strArg =
+    dyn_cast<StringLiteral>(CE->getArg((unsigned)ArgSuffix.first)
+                              ->IgnoreParenImpCasts());
+  
+  // Currently we only handle string literals.  It is possible to do better,
+  // either by looking at references to const variables, or by doing real
+  // flow analysis.
+  if (!strArg || strArg->getCharByteWidth() != 1)
+    return;
+
+  // Count the number of X's, taking into account a possible cutoff suffix.
+  StringRef str = strArg->getString();
+  unsigned numX = 0;
+  unsigned n = str.size();
+
+  // Take into account the suffix.
+  unsigned suffix = 0;
+  if (ArgSuffix.second >= 0) {
+    const Expr *suffixEx = CE->getArg((unsigned)ArgSuffix.second);
+    llvm::APSInt Result;
+    if (!suffixEx->EvaluateAsInt(Result, BR.getContext()))
+      return;
+    // FIXME: Issue a warning.
+    if (Result.isNegative())
+      return;
+    suffix = (unsigned) Result.getZExtValue();
+    n = (n > suffix) ? n - suffix : 0;
+  }
+  
+  for (unsigned i = 0; i < n; ++i)
+    if (str[i] == 'X') ++numX;
+  
+  if (numX >= 6)
+    return;
+  
+  // Issue a warning.
+  SourceRange R = strArg->getSourceRange();
+  PathDiagnosticLocation CELoc =
+    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
+  SmallString<512> buf;
+  llvm::raw_svector_ostream out(buf);
+  out << "Call to '" << Name << "' should have at least 6 'X's in the"
+    " format string to be secure (" << numX << " 'X'";
+  if (numX != 1)
+    out << 's';
+  out << " seen";
+  if (suffix) {
+    out << ", " << suffix << " character";
+    if (suffix > 1)
+      out << 's';
+    out << " used as a suffix";
+  }
+  out << ')';
+  BR.EmitBasicReport(AC->getDecl(),
+                     "Insecure temporary file creation", "Security",
+                     out.str(), CELoc, &R, 1);
+}
+
+//===----------------------------------------------------------------------===//
+// Check: Any use of 'strcpy' is insecure.
+//
+// CWE-119: Improper Restriction of Operations within 
+// the Bounds of a Memory Buffer 
+//===----------------------------------------------------------------------===//
+void WalkAST::checkCall_strcpy(const CallExpr *CE, const FunctionDecl *FD) {
+  if (!filter.check_strcpy)
+    return;
+  
+  if (!checkCall_strCommon(CE, FD))
+    return;
+
+  // Issue a warning.
+  SourceRange R = CE->getCallee()->getSourceRange();
+  PathDiagnosticLocation CELoc =
+    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
+  BR.EmitBasicReport(AC->getDecl(),
+                     "Potential insecure memory buffer bounds restriction in "
+                     "call 'strcpy'",
+                     "Security",
+                     "Call to function 'strcpy' is insecure as it does not "
+                     "provide bounding of the memory buffer. Replace "
+                     "unbounded copy functions with analogous functions that "
+                     "support length arguments such as 'strlcpy'. CWE-119.",
+                     CELoc, &R, 1);
+}
+
+//===----------------------------------------------------------------------===//
+// Check: Any use of 'strcat' is insecure.
+//
+// CWE-119: Improper Restriction of Operations within 
+// the Bounds of a Memory Buffer 
+//===----------------------------------------------------------------------===//
+void WalkAST::checkCall_strcat(const CallExpr *CE, const FunctionDecl *FD) {
+  if (!filter.check_strcpy)
+    return;
+
+  if (!checkCall_strCommon(CE, FD))
+    return;
+
+  // Issue a warning.
+  SourceRange R = CE->getCallee()->getSourceRange();
+  PathDiagnosticLocation CELoc =
+    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
+  BR.EmitBasicReport(AC->getDecl(),
+                     "Potential insecure memory buffer bounds restriction in "
+                     "call 'strcat'",
+                     "Security",
+                     "Call to function 'strcat' is insecure as it does not "
+                     "provide bounding of the memory buffer. Replace "
+                     "unbounded copy functions with analogous functions that "
+                     "support length arguments such as 'strlcat'. CWE-119.",
+                     CELoc, &R, 1);
+}
+
+//===----------------------------------------------------------------------===//
+// Common check for str* functions with no bounds parameters.
+//===----------------------------------------------------------------------===//
+bool WalkAST::checkCall_strCommon(const CallExpr *CE, const FunctionDecl *FD) {
+  const FunctionProtoType *FPT
+    = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
+  if (!FPT)
+    return false;
+
+  // Verify the function takes two arguments, three in the _chk version.
+  int numArgs = FPT->getNumArgs();
+  if (numArgs != 2 && numArgs != 3)
+    return false;
+
+  // Verify the type for both arguments.
+  for (int i = 0; i < 2; i++) {
+    // Verify that the arguments are pointers.
+    const PointerType *PT = dyn_cast<PointerType>(FPT->getArgType(i));
+    if (!PT)
+      return false;
+
+    // Verify that the argument is a 'char*'.
+    if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
+      return false;
+  }
+
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// Check: Linear congruent random number generators should not be used
+// Originally: <rdar://problem/63371000>
+// CWE-338: Use of cryptographically weak prng
+//===----------------------------------------------------------------------===//
+
+void WalkAST::checkCall_rand(const CallExpr *CE, const FunctionDecl *FD) {
+  if (!filter.check_rand || !CheckRand)
+    return;
+
+  const FunctionProtoType *FTP
+    = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
+  if (!FTP)
+    return;
+
+  if (FTP->getNumArgs() == 1) {
+    // Is the argument an 'unsigned short *'?
+    // (Actually any integer type is allowed.)
+    const PointerType *PT = dyn_cast<PointerType>(FTP->getArgType(0));
+    if (!PT)
+      return;
+
+    if (! PT->getPointeeType()->isIntegerType())
+      return;
+  }
+  else if (FTP->getNumArgs() != 0)
+    return;
+
+  // Issue a warning.
+  SmallString<256> buf1;
+  llvm::raw_svector_ostream os1(buf1);
+  os1 << '\'' << *FD << "' is a poor random number generator";
+
+  SmallString<256> buf2;
+  llvm::raw_svector_ostream os2(buf2);
+  os2 << "Function '" << *FD
+      << "' is obsolete because it implements a poor random number generator."
+      << "  Use 'arc4random' instead";
+
+  SourceRange R = CE->getCallee()->getSourceRange();
+  PathDiagnosticLocation CELoc =
+    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
+  BR.EmitBasicReport(AC->getDecl(), os1.str(), "Security", os2.str(),
+                     CELoc, &R, 1);
+}
+
+//===----------------------------------------------------------------------===//
+// Check: 'random' should not be used
+// Originally: <rdar://problem/63371000>
+//===----------------------------------------------------------------------===//
+
+void WalkAST::checkCall_random(const CallExpr *CE, const FunctionDecl *FD) {
+  if (!CheckRand || !filter.check_rand)
+    return;
+
+  const FunctionProtoType *FTP
+    = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
+  if (!FTP)
+    return;
+
+  // Verify that the function takes no argument.
+  if (FTP->getNumArgs() != 0)
+    return;
+
+  // Issue a warning.
+  SourceRange R = CE->getCallee()->getSourceRange();
+  PathDiagnosticLocation CELoc =
+    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
+  BR.EmitBasicReport(AC->getDecl(),
+                     "'random' is not a secure random number generator",
+                     "Security",
+                     "The 'random' function produces a sequence of values that "
+                     "an adversary may be able to predict.  Use 'arc4random' "
+                     "instead", CELoc, &R, 1);
+}
+
+//===----------------------------------------------------------------------===//
+// Check: 'vfork' should not be used.
+// POS33-C: Do not use vfork().
+//===----------------------------------------------------------------------===//
+
+void WalkAST::checkCall_vfork(const CallExpr *CE, const FunctionDecl *FD) {
+  if (!filter.check_vfork)
+    return;
+
+  // All calls to vfork() are insecure, issue a warning.
+  SourceRange R = CE->getCallee()->getSourceRange();
+  PathDiagnosticLocation CELoc =
+    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
+  BR.EmitBasicReport(AC->getDecl(),
+                     "Potential insecure implementation-specific behavior in "
+                     "call 'vfork'",
+                     "Security",
+                     "Call to function 'vfork' is insecure as it can lead to "
+                     "denial of service situations in the parent process. "
+                     "Replace calls to vfork with calls to the safer "
+                     "'posix_spawn' function",
+                     CELoc, &R, 1);
+}
+
+//===----------------------------------------------------------------------===//
+// Check: Should check whether privileges are dropped successfully.
+// Originally: <rdar://problem/6337132>
+//===----------------------------------------------------------------------===//
+
+void WalkAST::checkUncheckedReturnValue(CallExpr *CE) {
+  if (!filter.check_UncheckedReturn)
+    return;
+  
+  const FunctionDecl *FD = CE->getDirectCallee();
+  if (!FD)
+    return;
+
+  if (II_setid[0] == NULL) {
+    static const char * const identifiers[num_setids] = {
+      "setuid", "setgid", "seteuid", "setegid",
+      "setreuid", "setregid"
+    };
+
+    for (size_t i = 0; i < num_setids; i++)
+      II_setid[i] = &BR.getContext().Idents.get(identifiers[i]);
+  }
+
+  const IdentifierInfo *id = FD->getIdentifier();
+  size_t identifierid;
+
+  for (identifierid = 0; identifierid < num_setids; identifierid++)
+    if (id == II_setid[identifierid])
+      break;
+
+  if (identifierid >= num_setids)
+    return;
+
+  const FunctionProtoType *FTP
+    = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
+  if (!FTP)
+    return;
+
+  // Verify that the function takes one or two arguments (depending on
+  //   the function).
+  if (FTP->getNumArgs() != (identifierid < 4 ? 1 : 2))
+    return;
+
+  // The arguments must be integers.
+  for (unsigned i = 0; i < FTP->getNumArgs(); i++)
+    if (! FTP->getArgType(i)->isIntegerType())
+      return;
+
+  // Issue a warning.
+  SmallString<256> buf1;
+  llvm::raw_svector_ostream os1(buf1);
+  os1 << "Return value is not checked in call to '" << *FD << '\'';
+
+  SmallString<256> buf2;
+  llvm::raw_svector_ostream os2(buf2);
+  os2 << "The return value from the call to '" << *FD
+      << "' is not checked.  If an error occurs in '" << *FD
+      << "', the following code may execute with unexpected privileges";
+
+  SourceRange R = CE->getCallee()->getSourceRange();
+  PathDiagnosticLocation CELoc =
+    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
+  BR.EmitBasicReport(AC->getDecl(), os1.str(), "Security", os2.str(),
+                     CELoc, &R, 1);
+}
+
+//===----------------------------------------------------------------------===//
+// SecuritySyntaxChecker
+//===----------------------------------------------------------------------===//
+
+namespace {
+class SecuritySyntaxChecker : public Checker<check::ASTCodeBody> {
+public:
+  ChecksFilter filter;
+  
+  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
+                        BugReporter &BR) const {
+    WalkAST walker(BR, mgr.getAnalysisDeclContext(D), filter);
+    walker.Visit(D->getBody());
+  }
+};
+}
+
+#define REGISTER_CHECKER(name) \
+void ento::register##name(CheckerManager &mgr) {\
+  mgr.registerChecker<SecuritySyntaxChecker>()->filter.check_##name = true;\
+}
+
+REGISTER_CHECKER(gets)
+REGISTER_CHECKER(getpw)
+REGISTER_CHECKER(mkstemp)
+REGISTER_CHECKER(mktemp)
+REGISTER_CHECKER(strcpy)
+REGISTER_CHECKER(rand)
+REGISTER_CHECKER(vfork)
+REGISTER_CHECKER(FloatLoopCounter)
+REGISTER_CHECKER(UncheckedReturn)
+
+
diff --git a/clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp b/clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp
new file mode 100644
index 0000000..cc7fd37
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp
@@ -0,0 +1,92 @@
+//==- CheckSizeofPointer.cpp - Check for sizeof on pointers ------*- 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 check for unintended use of sizeof() on pointer
+//  expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class WalkAST : public StmtVisitor<WalkAST> {
+  BugReporter &BR;
+  AnalysisDeclContext* AC;
+
+public:
+  WalkAST(BugReporter &br, AnalysisDeclContext* ac) : BR(br), AC(ac) {}
+  void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E);
+  void VisitStmt(Stmt *S) { VisitChildren(S); }
+  void VisitChildren(Stmt *S);
+};
+}
+
+void WalkAST::VisitChildren(Stmt *S) {
+  for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
+    if (Stmt *child = *I)
+      Visit(child);
+}
+
+// CWE-467: Use of sizeof() on a Pointer Type
+void WalkAST::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) {
+  if (E->getKind() != UETT_SizeOf)
+    return;
+
+  // If an explicit type is used in the code, usually the coder knows what he is
+  // doing.
+  if (E->isArgumentType())
+    return;
+
+  QualType T = E->getTypeOfArgument();
+  if (T->isPointerType()) {
+
+    // Many false positives have the form 'sizeof *p'. This is reasonable 
+    // because people know what they are doing when they intentionally 
+    // dereference the pointer.
+    Expr *ArgEx = E->getArgumentExpr();
+    if (!isa<DeclRefExpr>(ArgEx->IgnoreParens()))
+      return;
+
+    SourceRange R = ArgEx->getSourceRange();
+    PathDiagnosticLocation ELoc =
+      PathDiagnosticLocation::createBegin(E, BR.getSourceManager(), AC);
+    BR.EmitBasicReport(AC->getDecl(),
+                       "Potential unintended use of sizeof() on pointer type",
+                       "Logic",
+                       "The code calls sizeof() on a pointer type. "
+                       "This can produce an unexpected result.",
+                       ELoc, &R, 1);
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// SizeofPointerChecker
+//===----------------------------------------------------------------------===//
+
+namespace {
+class SizeofPointerChecker : public Checker<check::ASTCodeBody> {
+public:
+  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
+                        BugReporter &BR) const {
+    WalkAST walker(BR, mgr.getAnalysisDeclContext(D));
+    walker.Visit(D->getBody());
+  }
+};
+}
+
+void ento::registerSizeofPointerChecker(CheckerManager &mgr) {
+  mgr.registerChecker<SizeofPointerChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp b/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
new file mode 100644
index 0000000..843502f
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
@@ -0,0 +1,233 @@
+//= CheckerDocumentation.cpp - Documentation checker ---------------*- C++ -*-//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This checker lists all the checker callbacks and provides documentation for
+// checker writers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+
+using namespace clang;
+using namespace ento;
+
+// All checkers should be placed into anonymous namespace.
+// We place the CheckerDocumentation inside ento namespace to make the
+// it visible in doxygen.
+namespace ento {
+
+/// This checker documents the callback functions checkers can use to implement
+/// the custom handling of the specific events during path exploration as well
+/// as reporting bugs. Most of the callbacks are targeted at path-sensitive
+/// checking.
+///
+/// \sa CheckerContext
+class CheckerDocumentation : public Checker< check::PreStmt<DeclStmt>,
+                                       check::PostStmt<CallExpr>,
+                                       check::PreObjCMessage,
+                                       check::PostObjCMessage,
+                                       check::BranchCondition,
+                                       check::Location,
+                                       check::Bind,
+                                       check::DeadSymbols,
+                                       check::EndPath,
+                                       check::EndAnalysis,
+                                       check::EndOfTranslationUnit,
+                                       eval::Call,
+                                       eval::Assume,
+                                       check::LiveSymbols,
+                                       check::RegionChanges,
+                                       check::Event<ImplicitNullDerefEvent>,
+                                       check::ASTDecl<FunctionDecl> > {
+public:
+
+  /// \brief Pre-visit the Statement.
+  ///
+  /// The method will be called before the analyzer core processes the
+  /// statement. The notification is performed for every explored CFGElement,
+  /// which does not include the control flow statements such as IfStmt. The
+  /// callback can be specialized to be called with any subclass of Stmt.
+  ///
+  /// See checkBranchCondition() callback for performing custom processing of
+  /// the branching statements.
+  ///
+  /// check::PreStmt<DeclStmt>
+  void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {}
+
+  /// \brief Post-visit the Statement.
+  ///
+  /// The method will be called after the analyzer core processes the
+  /// statement. The notification is performed for every explored CFGElement,
+  /// which does not include the control flow statements such as IfStmt. The
+  /// callback can be specialized to be called with any subclass of Stmt.
+  ///
+  /// check::PostStmt<DeclStmt>
+  void checkPostStmt(const CallExpr *DS, CheckerContext &C) const;
+
+  /// \brief Pre-visit the Objective C messages.
+  void checkPreObjCMessage(const ObjCMessage &Msg, CheckerContext &C) const {}
+
+  /// \brief Post-visit the Objective C messages.
+  void checkPostObjCMessage(const ObjCMessage &Msg, CheckerContext &C) const {}
+
+  /// \brief Pre-visit of the condition statement of a branch (such as IfStmt).
+  void checkBranchCondition(const Stmt *Condition, CheckerContext &Ctx) const {}
+
+  /// \brief Called on a load from and a store to a location.
+  ///
+  /// The method will be called each time a location (pointer) value is
+  /// accessed.
+  /// \param Loc    The value of the location (pointer).
+  /// \param IsLoad The flag specifying if the location is a store or a load.
+  /// \param S      The load is performed while processing the statement.
+  ///
+  /// check::Location
+  void checkLocation(SVal Loc, bool IsLoad, const Stmt *S,
+                     CheckerContext &C) const {}
+
+  /// \brief Called on binding of a value to a location.
+  ///
+  /// \param Loc The value of the location (pointer).
+  /// \param Val The value which will be stored at the location Loc.
+  /// \param S   The bind is performed while processing the statement S.
+  ///
+  /// check::Bind
+  void checkBind(SVal Loc, SVal Val, const Stmt *S, CheckerContext &C) const {}
+
+
+  /// \brief Called whenever a symbol becomes dead.
+  ///
+  /// This callback should be used by the checkers to aggressively clean
+  /// up/reduce the checker state, which is important for reducing the overall
+  /// memory usage. Specifically, if a checker keeps symbol specific information
+  /// in the sate, it can and should be dropped after the symbol becomes dead.
+  /// In addition, reporting a bug as soon as the checker becomes dead leads to
+  /// more precise diagnostics. (For example, one should report that a malloced
+  /// variable is not freed right after it goes out of scope.)
+  ///
+  /// \param SR The SymbolReaper object can be queried to determine which
+  ///           symbols are dead.
+  ///
+  /// check::DeadSymbols
+  void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const {}
+
+  /// \brief Called when an end of path is reached in the ExplodedGraph.
+  ///
+  /// This callback should be used to check if the allocated resources are freed.
+  ///
+  /// check::EndPath
+  void checkEndPath(CheckerContext &Ctx) const {}
+
+  /// \brief Called after all the paths in the ExplodedGraph reach end of path
+  /// - the symbolic execution graph is fully explored.
+  ///
+  /// This callback should be used in cases when a checker needs to have a
+  /// global view of the information generated on all paths. For example, to
+  /// compare execution summary/result several paths.
+  /// See IdempotentOperationChecker for a usage example.
+  ///
+  /// check::EndAnalysis
+  void checkEndAnalysis(ExplodedGraph &G,
+                        BugReporter &BR,
+                        ExprEngine &Eng) const {}
+
+  /// \brief Called after analysis of a TranslationUnit is complete.
+  ///
+  /// check::EndOfTranslationUnit
+  void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
+                                 AnalysisManager &Mgr,
+                                 BugReporter &BR) const {}
+
+
+  /// \brief Evaluates function call.
+  ///
+  /// The analysis core threats all function calls in the same way. However, some
+  /// functions have special meaning, which should be reflected in the program
+  /// state. This callback allows a checker to provide domain specific knowledge
+  /// about the particular functions it knows about.
+  ///
+  /// \returns true if the call has been successfully evaluated
+  /// and false otherwise. Note, that only one checker can evaluate a call. If
+  /// more then one checker claim that they can evaluate the same call the
+  /// first one wins.
+  ///
+  /// eval::Call
+  bool evalCall(const CallExpr *CE, CheckerContext &C) const { return true; }
+
+  /// \brief Handles assumptions on symbolic values.
+  ///
+  /// This method is called when a symbolic expression is assumed to be true or
+  /// false. For example, the assumptions are performed when evaluating a
+  /// condition at a branch. The callback allows checkers track the assumptions
+  /// performed on the symbols of interest and change the state accordingly.
+  ///
+  /// eval::Assume
+  ProgramStateRef evalAssume(ProgramStateRef State,
+                                 SVal Cond,
+                                 bool Assumption) const { return State; }
+
+  /// Allows modifying SymbolReaper object. For example, checkers can explicitly
+  /// register symbols of interest as live. These symbols will not be marked
+  /// dead and removed.
+  ///
+  /// check::LiveSymbols
+  void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SR) const {}
+
+
+  bool wantsRegionChangeUpdate(ProgramStateRef St) const { return true; }
+  
+  /// check::RegionChanges
+  /// Allows tracking regions which get invalidated.
+  /// \param state The current program state.
+  /// \param invalidated A set of all symbols potentially touched by the change.
+  /// \param ExplicitRegions The regions explicitly requested for invalidation.
+  ///   For example, in the case of a function call, these would be arguments.
+  /// \param Regions The transitive closure of accessible regions,
+  ///   i.e. all regions that may have been touched by this change.
+  /// \param The call expression wrapper if the regions are invalidated by a
+  ///   call, 0 otherwise.
+  /// Note, in order to be notified, the checker should also implement 
+  /// wantsRegionChangeUpdate callback.
+  ProgramStateRef 
+    checkRegionChanges(ProgramStateRef State,
+                       const StoreManager::InvalidatedSymbols *,
+                       ArrayRef<const MemRegion *> ExplicitRegions,
+                       ArrayRef<const MemRegion *> Regions,
+                       const CallOrObjCMessage *Call) const {
+    return State;
+  }
+
+  /// check::Event<ImplicitNullDerefEvent>
+  void checkEvent(ImplicitNullDerefEvent Event) const {}
+
+  /// \brief Check every declaration in the AST.
+  ///
+  /// An AST traversal callback, which should only be used when the checker is
+  /// not path sensitive. It will be called for every Declaration in the AST and
+  /// can be specialized to only be called on subclasses of Decl, for example,
+  /// FunctionDecl.
+  ///
+  /// check::ASTDecl<FunctionDecl>
+  void checkASTDecl(const FunctionDecl *D,
+                    AnalysisManager &Mgr,
+                    BugReporter &BR) const {}
+
+};
+
+void CheckerDocumentation::checkPostStmt(const CallExpr *DS,
+                                         CheckerContext &C) const {
+  return;
+}
+
+} // end namespace
diff --git a/clang/lib/StaticAnalyzer/Checkers/Checkers.td b/clang/lib/StaticAnalyzer/Checkers/Checkers.td
new file mode 100644
index 0000000..f577a89
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/Checkers.td
@@ -0,0 +1,491 @@
+//===--- Checkers.td - Static Analyzer Checkers -===-----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+include "clang/StaticAnalyzer/Checkers/CheckerBase.td"
+
+//===----------------------------------------------------------------------===//
+// Packages.
+//===----------------------------------------------------------------------===//
+
+def Experimental : Package<"experimental">;
+
+def Core : Package<"core">;
+def CoreBuiltin : Package<"builtin">, InPackage<Core>;
+def CoreUninitialized  : Package<"uninitialized">, InPackage<Core>;
+def CoreExperimental : Package<"core">, InPackage<Experimental>, Hidden;
+
+def Cplusplus : Package<"cplusplus">;
+def CplusplusExperimental : Package<"cplusplus">, InPackage<Experimental>, Hidden;
+
+def DeadCode : Package<"deadcode">;
+def DeadCodeExperimental : Package<"deadcode">, InPackage<Experimental>, Hidden;
+
+def Security : Package <"security">;
+def InsecureAPI : Package<"insecureAPI">, InPackage<Security>;
+def SecurityExperimental : Package<"security">, InPackage<Experimental>, Hidden;
+def Taint : Package<"taint">, InPackage<SecurityExperimental>, Hidden;  
+
+def Unix : Package<"unix">;
+def UnixExperimental : Package<"unix">, InPackage<Experimental>, Hidden;
+def CString : Package<"cstring">, InPackage<Unix>, Hidden;
+def CStringExperimental : Package<"cstring">, InPackage<UnixExperimental>, Hidden;
+
+def OSX : Package<"osx">;
+def OSXExperimental : Package<"osx">, InPackage<Experimental>, Hidden;
+def Cocoa : Package<"cocoa">, InPackage<OSX>;
+def CocoaExperimental : Package<"cocoa">, InPackage<OSXExperimental>, Hidden;
+def CoreFoundation : Package<"coreFoundation">, InPackage<OSX>;
+def Containers : Package<"containers">, InPackage<CoreFoundation>;
+
+def LLVM : Package<"llvm">;
+def Debug : Package<"debug">;
+
+//===----------------------------------------------------------------------===//
+// Core Checkers.
+//===----------------------------------------------------------------------===//
+
+let ParentPackage = Core in {
+
+def DereferenceChecker : Checker<"NullDereference">,
+  HelpText<"Check for dereferences of null pointers">,
+  DescFile<"DereferenceChecker.cpp">;
+
+def CallAndMessageChecker : Checker<"CallAndMessage">,
+  HelpText<"Check for logical errors for function calls and Objective-C message expressions (e.g., uninitialized arguments, null function pointers)">,
+  DescFile<"CallAndMessageChecker.cpp">;
+
+def AdjustedReturnValueChecker : Checker<"AdjustedReturnValue">,
+  HelpText<"Check to see if the return value of a function call is different than the caller expects (e.g., from calls through function pointers)">,
+  DescFile<"AdjustedReturnValueChecker.cpp">;
+
+def AttrNonNullChecker : Checker<"AttributeNonNull">,
+  HelpText<"Check for null pointers passed as arguments to a function whose arguments are marked with the 'nonnull' attribute">,
+  DescFile<"AttrNonNullChecker.cpp">;
+
+def VLASizeChecker : Checker<"VLASize">,
+  HelpText<"Check for declarations of VLA of undefined or zero size">,
+  DescFile<"VLASizeChecker.cpp">;
+
+def DivZeroChecker : Checker<"DivideZero">,
+  HelpText<"Check for division by zero">,
+  DescFile<"DivZeroChecker.cpp">;
+
+def UndefResultChecker : Checker<"UndefinedBinaryOperatorResult">,
+  HelpText<"Check for undefined results of binary operators">,
+  DescFile<"UndefResultChecker.cpp">;
+
+def StackAddrEscapeChecker : Checker<"StackAddressEscape">,
+  HelpText<"Check that addresses to stack memory do not escape the function">,
+  DescFile<"StackAddrEscapeChecker.cpp">;
+
+} // end "core"
+
+let ParentPackage = CoreExperimental in {
+
+def BoolAssignmentChecker : Checker<"BoolAssignment">,
+  HelpText<"Warn about assigning non-{0,1} values to Boolean variables">,
+  DescFile<"BoolAssignmentChecker.cpp">;
+
+def CastSizeChecker : Checker<"CastSize">,
+  HelpText<"Check when casting a malloc'ed type T, whether the size is a multiple of the size of T">,
+  DescFile<"CastSizeChecker.cpp">;
+
+def CastToStructChecker : Checker<"CastToStruct">,
+  HelpText<"Check for cast from non-struct pointer to struct pointer">,
+  DescFile<"CastToStructChecker.cpp">;
+
+def FixedAddressChecker : Checker<"FixedAddr">,
+  HelpText<"Check for assignment of a fixed address to a pointer">,
+  DescFile<"FixedAddressChecker.cpp">;
+
+def PointerArithChecker : Checker<"PointerArithm">,
+  HelpText<"Check for pointer arithmetic on locations other than array elements">,
+  DescFile<"PointerArithChecker">;
+
+def PointerSubChecker : Checker<"PointerSub">,
+  HelpText<"Check for pointer subtractions on two pointers pointing to different memory chunks">,
+  DescFile<"PointerSubChecker">;
+
+def SizeofPointerChecker : Checker<"SizeofPtr">,
+  HelpText<"Warn about unintended use of sizeof() on pointer expressions">,
+  DescFile<"CheckSizeofPointer.cpp">;
+
+} // end "core.experimental"
+
+//===----------------------------------------------------------------------===//
+// Evaluate "builtin" functions.
+//===----------------------------------------------------------------------===//
+
+let ParentPackage = CoreBuiltin in {
+
+def NoReturnFunctionChecker : Checker<"NoReturnFunctions">,
+  HelpText<"Evaluate \"panic\" functions that are known to not return to the caller">,
+  DescFile<"NoReturnFunctionChecker.cpp">;
+
+def BuiltinFunctionChecker : Checker<"BuiltinFunctions">,
+  HelpText<"Evaluate compiler builtin functions (e.g., alloca())">,
+  DescFile<"BuiltinFunctionChecker.cpp">;
+
+} // end "core.builtin"
+
+//===----------------------------------------------------------------------===//
+// Uninitialized values checkers.
+//===----------------------------------------------------------------------===//
+
+let ParentPackage = CoreUninitialized in {
+
+def UndefinedArraySubscriptChecker : Checker<"ArraySubscript">,
+  HelpText<"Check for uninitialized values used as array subscripts">,
+  DescFile<"UndefinedArraySubscriptChecker.cpp">;
+
+def UndefinedAssignmentChecker : Checker<"Assign">,
+  HelpText<"Check for assigning uninitialized values">,
+  DescFile<"UndefinedAssignmentChecker.cpp">;
+
+def UndefBranchChecker : Checker<"Branch">,
+  HelpText<"Check for uninitialized values used as branch conditions">,
+  DescFile<"UndefBranchChecker.cpp">;
+
+def UndefCapturedBlockVarChecker : Checker<"CapturedBlockVariable">,
+  HelpText<"Check for blocks that capture uninitialized values">,
+  DescFile<"UndefCapturedBlockVarChecker.cpp">;
+  
+def ReturnUndefChecker : Checker<"UndefReturn">,
+  HelpText<"Check for uninitialized values being returned to the caller">,
+  DescFile<"ReturnUndefChecker.cpp">;
+
+} // end "core.uninitialized"
+
+//===----------------------------------------------------------------------===//
+// C++ checkers.
+//===----------------------------------------------------------------------===//
+
+let ParentPackage = CplusplusExperimental in {
+
+def IteratorsChecker : Checker<"Iterators">,
+  HelpText<"Check improper uses of STL vector iterators">,
+  DescFile<"IteratorsChecker.cpp">;
+
+def VirtualCallChecker : Checker<"VirtualCall">,
+  HelpText<"Check virtual function calls during construction or destruction">, 
+  DescFile<"VirtualCallChecker.cpp">;
+
+} // end: "cplusplus.experimental"
+
+//===----------------------------------------------------------------------===//
+// Deadcode checkers.
+//===----------------------------------------------------------------------===//
+
+let ParentPackage = DeadCode in {
+
+def DeadStoresChecker : Checker<"DeadStores">,
+  HelpText<"Check for values stored to variables that are never read afterwards">,
+  DescFile<"DeadStoresChecker.cpp">;
+} // end DeadCode
+
+let ParentPackage = DeadCodeExperimental in {
+
+def IdempotentOperationChecker : Checker<"IdempotentOperations">,
+  HelpText<"Warn about idempotent operations">,
+  DescFile<"IdempotentOperationChecker.cpp">;
+
+def UnreachableCodeChecker : Checker<"UnreachableCode">,
+  HelpText<"Check unreachable code">,
+  DescFile<"UnreachableCodeChecker.cpp">;
+
+} // end "deadcode.experimental"
+
+//===----------------------------------------------------------------------===//
+// Security checkers.
+//===----------------------------------------------------------------------===//
+
+let ParentPackage = InsecureAPI in {
+  def gets : Checker<"gets">,
+    HelpText<"Warn on uses of the 'gets' function">,
+    DescFile<"CheckSecuritySyntaxOnly.cpp">;
+  def getpw : Checker<"getpw">,
+    HelpText<"Warn on uses of the 'getpw' function">,
+    DescFile<"CheckSecuritySyntaxOnly.cpp">;
+  def mktemp : Checker<"mktemp">,
+    HelpText<"Warn on uses of the 'mktemp' function">,
+    DescFile<"CheckSecuritySyntaxOnly.cpp">;
+  def mkstemp : Checker<"mkstemp">,
+    HelpText<"Warn when 'mkstemp' is passed fewer than 6 X's in the format string">,
+    DescFile<"CheckSecuritySyntaxOnly.cpp">;
+  def rand : Checker<"rand">,
+    HelpText<"Warn on uses of the 'rand', 'random', and related functions">,
+    DescFile<"CheckSecuritySyntaxOnly.cpp">;
+  def strcpy : Checker<"strcpy">,
+    HelpText<"Warn on uses of the 'strcpy' and 'strcat' functions">,
+    DescFile<"CheckSecuritySyntaxOnly.cpp">;
+  def vfork : Checker<"vfork">,
+    HelpText<"Warn on uses of the 'vfork' function">,
+    DescFile<"CheckSecuritySyntaxOnly.cpp">;
+  def UncheckedReturn : Checker<"UncheckedReturn">,
+    HelpText<"Warn on uses of functions whose return values must be always checked">,
+    DescFile<"CheckSecuritySyntaxOnly.cpp">;
+}
+let ParentPackage = Security in {
+  def FloatLoopCounter : Checker<"FloatLoopCounter">,
+    HelpText<"Warn on using a floating point value as a loop counter (CERT: FLP30-C, FLP30-CPP)">,
+    DescFile<"CheckSecuritySyntaxOnly.cpp">;
+}
+
+let ParentPackage = SecurityExperimental in {
+
+def ArrayBoundChecker : Checker<"ArrayBound">,
+  HelpText<"Warn about buffer overflows (older checker)">,
+  DescFile<"ArrayBoundChecker.cpp">;  
+
+def ArrayBoundCheckerV2 : Checker<"ArrayBoundV2">,
+  HelpText<"Warn about buffer overflows (newer checker)">,
+  DescFile<"ArrayBoundCheckerV2.cpp">;
+
+def ReturnPointerRangeChecker : Checker<"ReturnPtrRange">,
+  HelpText<"Check for an out-of-bound pointer being returned to callers">,
+  DescFile<"ReturnPointerRangeChecker.cpp">;
+
+def MallocOverflowSecurityChecker : Checker<"MallocOverflow">,
+  HelpText<"Check for overflows in the arguments to malloc()">,
+  DescFile<"MallocOverflowSecurityChecker.cpp">;
+
+} // end "security.experimental"
+
+//===----------------------------------------------------------------------===//
+// Taint checkers.
+//===----------------------------------------------------------------------===//
+
+let ParentPackage = Taint in {
+
+def GenericTaintChecker : Checker<"TaintPropagation">,
+  HelpText<"Generate taint information used by other checkers">,
+  DescFile<"GenericTaintChecker.cpp">;
+
+} // end "experimental.security.taint"
+
+//===----------------------------------------------------------------------===//
+// Unix API checkers.
+//===----------------------------------------------------------------------===//
+
+let ParentPackage = Unix in {
+
+def UnixAPIChecker : Checker<"API">,
+  HelpText<"Check calls to various UNIX/Posix functions">,
+  DescFile<"UnixAPIChecker.cpp">;
+
+def MallocPessimistic : Checker<"Malloc">,
+  HelpText<"Check for memory leaks, double free, and use-after-free problems.">,
+  DescFile<"MallocChecker.cpp">;
+  
+} // end "unix"
+
+let ParentPackage = UnixExperimental in {
+
+def ChrootChecker : Checker<"Chroot">,
+  HelpText<"Check improper use of chroot">,
+  DescFile<"ChrootChecker.cpp">;
+
+def MallocOptimistic : Checker<"MallocWithAnnotations">,
+  HelpText<"Check for memory leaks, double free, and use-after-free problems. Assumes that all user-defined functions which might free a pointer are annotated.">,
+  DescFile<"MallocChecker.cpp">;
+
+def MallocSizeofChecker : Checker<"MallocSizeof">,
+  HelpText<"Check for dubious malloc arguments involving sizeof">,
+  DescFile<"MallocSizeofChecker.cpp">;
+
+def PthreadLockChecker : Checker<"PthreadLock">,
+  HelpText<"Simple lock -> unlock checker">,
+  DescFile<"PthreadLockChecker.cpp">;
+
+def StreamChecker : Checker<"Stream">,
+  HelpText<"Check stream handling functions">,
+  DescFile<"StreamChecker.cpp">;
+
+} // end "unix.experimental"
+
+let ParentPackage = CString in {
+
+def CStringNullArg : Checker<"NullArg">,
+  HelpText<"Check for null pointers being passed as arguments to C string functions">,
+  DescFile<"CStringChecker.cpp">;
+
+def CStringSyntaxChecker : Checker<"BadSizeArg">,
+  HelpText<"Check the size argument passed into C string functions for common erroneous patterns">,
+  DescFile<"CStringSyntaxChecker.cpp">;  
+}
+
+let ParentPackage = CStringExperimental in {
+
+def CStringOutOfBounds : Checker<"OutOfBounds">,
+  HelpText<"Check for out-of-bounds access in string functions">,
+  DescFile<"CStringChecker.cpp">;
+
+def CStringBufferOverlap : Checker<"BufferOverlap">,
+  HelpText<"Checks for overlap in two buffer arguments">,
+  DescFile<"CStringChecker.cpp">;
+
+def CStringNotNullTerm : Checker<"NotNullTerminated">,
+  HelpText<"Check for arguments which are not null-terminating strings">,
+  DescFile<"CStringChecker.cpp">;
+}
+
+//===----------------------------------------------------------------------===//
+// Mac OS X, Cocoa, and Core Foundation checkers.
+//===----------------------------------------------------------------------===//
+
+let ParentPackage = OSX in {
+
+def MacOSXAPIChecker : Checker<"API">,
+  InPackage<OSX>,
+  HelpText<"Check for proper uses of various Mac OS X APIs">,
+  DescFile<"MacOSXAPIChecker.cpp">;
+
+def OSAtomicChecker : Checker<"AtomicCAS">,
+  InPackage<OSX>,
+  HelpText<"Evaluate calls to OSAtomic functions">,
+  DescFile<"OSAtomicChecker.cpp">;
+
+def MacOSKeychainAPIChecker : Checker<"SecKeychainAPI">,
+  InPackage<OSX>,
+  HelpText<"Check for proper uses of Secure Keychain APIs">,
+  DescFile<"MacOSKeychainAPIChecker.cpp">;
+
+} // end "macosx"
+
+let ParentPackage = Cocoa in {
+
+def ObjCAtSyncChecker : Checker<"AtSync">,
+  HelpText<"Check for null pointers used as mutexes for @synchronized">,
+  DescFile<"ObjCAtSyncChecker.cpp">;
+
+def NilArgChecker : Checker<"NilArg">,
+  HelpText<"Check for prohibited nil arguments to ObjC method calls">,
+  DescFile<"BasicObjCFoundationChecks.cpp">;
+
+def ClassReleaseChecker : Checker<"ClassRelease">,
+  HelpText<"Check for sending 'retain', 'release', or 'autorelease' directly to a Class">,
+  DescFile<"BasicObjCFoundationChecks.cpp">;
+
+def VariadicMethodTypeChecker : Checker<"VariadicMethodTypes">,
+  HelpText<"Check for passing non-Objective-C types to variadic methods that expect "
+           "only Objective-C types">,
+  DescFile<"BasicObjCFoundationChecks.cpp">;
+
+def NSAutoreleasePoolChecker : Checker<"NSAutoreleasePool">,
+  HelpText<"Warn for suboptimal uses of NSAutoreleasePool in Objective-C GC mode">,
+  DescFile<"NSAutoreleasePoolChecker.cpp">;
+
+def ObjCMethSigsChecker : Checker<"IncompatibleMethodTypes">,
+  HelpText<"Warn about Objective-C method signatures with type incompatibilities">,
+  DescFile<"CheckObjCInstMethSignature.cpp">;
+
+def ObjCUnusedIvarsChecker : Checker<"UnusedIvars">,
+  HelpText<"Warn about private ivars that are never used">,
+  DescFile<"ObjCUnusedIVarsChecker.cpp">;
+
+def ObjCSelfInitChecker : Checker<"SelfInit">,
+  HelpText<"Check that 'self' is properly initialized inside an initializer method">,
+  DescFile<"ObjCSelfInitChecker.cpp">;
+
+def NSErrorChecker : Checker<"NSError">,
+  HelpText<"Check usage of NSError** parameters">,
+  DescFile<"NSErrorChecker.cpp">;
+
+def RetainCountChecker : Checker<"RetainCount">,
+  HelpText<"Check for leaks and improper reference count management">,
+  DescFile<"RetainCountChecker.cpp">;
+
+} // end "cocoa"
+
+let ParentPackage = CocoaExperimental in {
+
+def ObjCDeallocChecker : Checker<"Dealloc">,
+  HelpText<"Warn about Objective-C classes that lack a correct implementation of -dealloc">,
+  DescFile<"CheckObjCDealloc.cpp">;
+
+} // end "cocoa.experimental"
+
+let ParentPackage = CoreFoundation in {
+
+def CFNumberCreateChecker : Checker<"CFNumber">,
+  HelpText<"Check for proper uses of CFNumberCreate">,
+  DescFile<"BasicObjCFoundationChecks.cpp">;
+
+def CFRetainReleaseChecker : Checker<"CFRetainRelease">,
+  HelpText<"Check for null arguments to CFRetain/CFRelease">,
+  DescFile<"BasicObjCFoundationChecks.cpp">;
+
+def CFErrorChecker : Checker<"CFError">,
+  HelpText<"Check usage of CFErrorRef* parameters">,
+  DescFile<"NSErrorChecker.cpp">;
+}
+
+let ParentPackage = Containers in {
+def ObjCContainersASTChecker : Checker<"PointerSizedValues">,
+  HelpText<"Warns if 'CFArray', 'CFDictionary', 'CFSet' are created with non-pointer-size values">,
+  DescFile<"ObjCContainersASTChecker.cpp">;
+
+def ObjCContainersChecker : Checker<"OutOfBounds">,
+  HelpText<"Checks for index out-of-bounds when using 'CFArray' API">,
+  DescFile<"ObjCContainersChecker.cpp">;
+    
+}
+//===----------------------------------------------------------------------===//
+// Checkers for LLVM development.
+//===----------------------------------------------------------------------===//
+
+def LLVMConventionsChecker : Checker<"Conventions">,
+  InPackage<LLVM>,
+  HelpText<"Check code for LLVM codebase conventions">,
+  DescFile<"LLVMConventionsChecker.cpp">;
+
+//===----------------------------------------------------------------------===//
+// Debugging checkers (for analyzer development).
+//===----------------------------------------------------------------------===//
+
+let ParentPackage = Debug in {
+
+def DominatorsTreeDumper : Checker<"DumpDominators">,
+  HelpText<"Print the dominance tree for a given CFG">,
+  DescFile<"DebugCheckers.cpp">;
+
+def LiveVariablesDumper : Checker<"DumpLiveVars">,
+  HelpText<"Print results of live variable analysis">,
+  DescFile<"DebugCheckers.cpp">;
+
+def CFGViewer : Checker<"ViewCFG">,
+  HelpText<"View Control-Flow Graphs using GraphViz">,
+  DescFile<"DebugCheckers.cpp">;
+
+def CFGDumper : Checker<"DumpCFG">,
+  HelpText<"Display Control-Flow Graphs">,
+  DescFile<"DebugCheckers.cpp">;
+
+def CallGraphViewer : Checker<"ViewCallGraph">,
+  HelpText<"View Call Graph using GraphViz">,
+  DescFile<"DebugCheckers.cpp">;
+
+def CallGraphDumper : Checker<"DumpCallGraph">,
+  HelpText<"Display Call Graph">,
+  DescFile<"DebugCheckers.cpp">;
+
+def AnalyzerStatsChecker : Checker<"Stats">,
+  HelpText<"Emit warnings with analyzer statistics">,
+  DescFile<"AnalyzerStatsChecker.cpp">;
+
+def TaintTesterChecker : Checker<"TaintTest">,
+  HelpText<"Mark tainted symbols as such.">,
+  DescFile<"TaintTesterChecker.cpp">;
+
+def IntervalTestChecker : Checker<"IntervalTest">,
+  HelpText<"Test the IntervalAnalysis stuff">,
+  DescFile<"IntervalTest.cpp">;
+
+} // end "debug"
+
diff --git a/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
new file mode 100644
index 0000000..30d0609
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
@@ -0,0 +1,158 @@
+//===- Chrootchecker.cpp -------- Basic security checks ----------*- 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 chroot checker, which checks improper use of chroot.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/ImmutableMap.h"
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+// enum value that represent the jail state
+enum Kind { NO_CHROOT, ROOT_CHANGED, JAIL_ENTERED };
+  
+bool isRootChanged(intptr_t k) { return k == ROOT_CHANGED; }
+//bool isJailEntered(intptr_t k) { return k == JAIL_ENTERED; }
+
+// This checker checks improper use of chroot.
+// The state transition:
+// NO_CHROOT ---chroot(path)--> ROOT_CHANGED ---chdir(/) --> JAIL_ENTERED
+//                                  |                               |
+//         ROOT_CHANGED<--chdir(..)--      JAIL_ENTERED<--chdir(..)--
+//                                  |                               |
+//                      bug<--foo()--          JAIL_ENTERED<--foo()--
+class ChrootChecker : public Checker<eval::Call, check::PreStmt<CallExpr> > {
+  mutable IdentifierInfo *II_chroot, *II_chdir;
+  // This bug refers to possibly break out of a chroot() jail.
+  mutable OwningPtr<BuiltinBug> BT_BreakJail;
+
+public:
+  ChrootChecker() : II_chroot(0), II_chdir(0) {}
+  
+  static void *getTag() {
+    static int x;
+    return &x;
+  }
+  
+  bool evalCall(const CallExpr *CE, CheckerContext &C) const;
+  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
+
+private:
+  void Chroot(CheckerContext &C, const CallExpr *CE) const;
+  void Chdir(CheckerContext &C, const CallExpr *CE) const;
+};
+
+} // end anonymous namespace
+
+bool ChrootChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
+  const FunctionDecl *FD = C.getCalleeDecl(CE);
+  if (!FD)
+    return false;
+
+  ASTContext &Ctx = C.getASTContext();
+  if (!II_chroot)
+    II_chroot = &Ctx.Idents.get("chroot");
+  if (!II_chdir)
+    II_chdir = &Ctx.Idents.get("chdir");
+
+  if (FD->getIdentifier() == II_chroot) {
+    Chroot(C, CE);
+    return true;
+  }
+  if (FD->getIdentifier() == II_chdir) {
+    Chdir(C, CE);
+    return true;
+  }
+
+  return false;
+}
+
+void ChrootChecker::Chroot(CheckerContext &C, const CallExpr *CE) const {
+  ProgramStateRef state = C.getState();
+  ProgramStateManager &Mgr = state->getStateManager();
+  
+  // Once encouter a chroot(), set the enum value ROOT_CHANGED directly in 
+  // the GDM.
+  state = Mgr.addGDM(state, ChrootChecker::getTag(), (void*) ROOT_CHANGED);
+  C.addTransition(state);
+}
+
+void ChrootChecker::Chdir(CheckerContext &C, const CallExpr *CE) const {
+  ProgramStateRef state = C.getState();
+  ProgramStateManager &Mgr = state->getStateManager();
+
+  // If there are no jail state in the GDM, just return.
+  const void *k = state->FindGDM(ChrootChecker::getTag());
+  if (!k)
+    return;
+
+  // After chdir("/"), enter the jail, set the enum value JAIL_ENTERED.
+  const Expr *ArgExpr = CE->getArg(0);
+  SVal ArgVal = state->getSVal(ArgExpr, C.getLocationContext());
+  
+  if (const MemRegion *R = ArgVal.getAsRegion()) {
+    R = R->StripCasts();
+    if (const StringRegion* StrRegion= dyn_cast<StringRegion>(R)) {
+      const StringLiteral* Str = StrRegion->getStringLiteral();
+      if (Str->getString() == "/")
+        state = Mgr.addGDM(state, ChrootChecker::getTag(),
+                           (void*) JAIL_ENTERED);
+    }
+  }
+
+  C.addTransition(state);
+}
+
+// Check the jail state before any function call except chroot and chdir().
+void ChrootChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
+  const FunctionDecl *FD = C.getCalleeDecl(CE);
+  if (!FD)
+    return;
+
+  ASTContext &Ctx = C.getASTContext();
+  if (!II_chroot)
+    II_chroot = &Ctx.Idents.get("chroot");
+  if (!II_chdir)
+    II_chdir = &Ctx.Idents.get("chdir");
+
+  // Ingnore chroot and chdir.
+  if (FD->getIdentifier() == II_chroot || FD->getIdentifier() == II_chdir)
+    return;
+  
+  // If jail state is ROOT_CHANGED, generate BugReport.
+  void *const* k = C.getState()->FindGDM(ChrootChecker::getTag());
+  if (k)
+    if (isRootChanged((intptr_t) *k))
+      if (ExplodedNode *N = C.addTransition()) {
+        if (!BT_BreakJail)
+          BT_BreakJail.reset(new BuiltinBug("Break out of jail",
+                                        "No call of chdir(\"/\") immediately "
+                                        "after chroot"));
+        BugReport *R = new BugReport(*BT_BreakJail, 
+                                     BT_BreakJail->getDescription(), N);
+        C.EmitReport(R);
+      }
+  
+  return;
+}
+
+void ento::registerChrootChecker(CheckerManager &mgr) {
+  mgr.registerChecker<ChrootChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/ClangCheckers.cpp b/clang/lib/StaticAnalyzer/Checkers/ClangCheckers.cpp
new file mode 100644
index 0000000..77a5a72
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/ClangCheckers.cpp
@@ -0,0 +1,32 @@
+//===--- ClangCheckers.h - Provides builtin checkers ------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Checkers/ClangCheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerRegistry.h"
+
+// FIXME: This is only necessary as long as there are checker registration
+// functions that do additional work besides mgr.registerChecker<CLASS>().
+// The only checkers that currently do this are:
+// - NSAutoreleasePoolChecker
+// - NSErrorChecker
+// - ObjCAtSyncChecker
+// It's probably worth including this information in Checkers.td to minimize
+// boilerplate code.
+#include "ClangSACheckers.h"
+
+using namespace clang;
+using namespace ento;
+
+void ento::registerBuiltinCheckers(CheckerRegistry &registry) {
+#define GET_CHECKERS
+#define CHECKER(FULLNAME,CLASS,DESCFILE,HELPTEXT,GROUPINDEX,HIDDEN)    \
+  registry.addChecker(register##CLASS, FULLNAME, HELPTEXT);
+#include "Checkers.inc"
+#undef GET_CHECKERS
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/ClangSACheckers.h b/clang/lib/StaticAnalyzer/Checkers/ClangSACheckers.h
new file mode 100644
index 0000000..230baa7
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/ClangSACheckers.h
@@ -0,0 +1,37 @@
+//===--- ClangSACheckers.h - Registration functions for Checkers *- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Declares the registation functions for the checkers defined in
+// libclangStaticAnalyzerCheckers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Checkers/CommonBugCategories.h"
+
+#ifndef LLVM_CLANG_SA_LIB_CHECKERS_CLANGSACHECKERS_H
+#define LLVM_CLANG_SA_LIB_CHECKERS_CLANGSACHECKERS_H
+
+namespace clang {
+
+namespace ento {
+class CheckerManager;
+class CheckerRegistry;
+
+#define GET_CHECKERS
+#define CHECKER(FULLNAME,CLASS,CXXFILE,HELPTEXT,GROUPINDEX,HIDDEN)    \
+  void register##CLASS(CheckerManager &mgr);
+#include "Checkers.inc"
+#undef CHECKER
+#undef GET_CHECKERS
+
+} // end ento namespace
+
+} // end clang namespace
+
+#endif
diff --git a/clang/lib/StaticAnalyzer/Checkers/CommonBugCategories.cpp b/clang/lib/StaticAnalyzer/Checkers/CommonBugCategories.cpp
new file mode 100644
index 0000000..e2a8ea6
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/CommonBugCategories.cpp
@@ -0,0 +1,18 @@
+//=--- CommonBugCategories.cpp - Provides common issue categories -*- C++ -*-=//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Common strings used for the "category" of many static analyzer issues.
+namespace clang { namespace ento { namespace categories {
+
+const char *CoreFoundationObjectiveC = "Core Foundation/Objective-C";
+const char *MemoryCoreFoundationObjectiveC =
+  "Memory (Core Foundation/Objective-C)";
+const char *UnixAPI = "Unix API";
+}}}
+
diff --git a/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
new file mode 100644
index 0000000..510e8cd
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
@@ -0,0 +1,386 @@
+//==- DeadStoresChecker.cpp - Check for stores to dead variables -*- 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 DeadStores, a flow-sensitive checker that looks for
+//  stores to variables that are no longer live.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/Analysis/Analyses/LiveVariables.h"
+#include "clang/Analysis/Visitors/CFGRecStmtVisitor.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ParentMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+// FIXME: Eventually migrate into its own file, and have it managed by
+// AnalysisManager.
+class ReachableCode {
+  const CFG &cfg;
+  llvm::BitVector reachable;
+public:
+  ReachableCode(const CFG &cfg)
+    : cfg(cfg), reachable(cfg.getNumBlockIDs(), false) {}
+  
+  void computeReachableBlocks();
+  
+  bool isReachable(const CFGBlock *block) const {
+    return reachable[block->getBlockID()];
+  }
+};
+}
+
+void ReachableCode::computeReachableBlocks() {
+  if (!cfg.getNumBlockIDs())
+    return;
+  
+  SmallVector<const CFGBlock*, 10> worklist;
+  worklist.push_back(&cfg.getEntry());
+  
+  while (!worklist.empty()) {
+    const CFGBlock *block = worklist.back();
+    worklist.pop_back();
+    llvm::BitVector::reference isReachable = reachable[block->getBlockID()];
+    if (isReachable)
+      continue;
+    isReachable = true;
+    for (CFGBlock::const_succ_iterator i = block->succ_begin(),
+                                       e = block->succ_end(); i != e; ++i)
+      if (const CFGBlock *succ = *i)
+        worklist.push_back(succ);
+  }
+}
+
+static const Expr *LookThroughTransitiveAssignments(const Expr *Ex) {
+  while (Ex) {
+    const BinaryOperator *BO =
+      dyn_cast<BinaryOperator>(Ex->IgnoreParenCasts());
+    if (!BO)
+      break;
+    if (BO->getOpcode() == BO_Assign) {
+      Ex = BO->getRHS();
+      continue;
+    }
+    break;
+  }
+  return Ex;
+}
+
+namespace {
+class DeadStoreObs : public LiveVariables::Observer {
+  const CFG &cfg;
+  ASTContext &Ctx;
+  BugReporter& BR;
+  AnalysisDeclContext* AC;
+  ParentMap& Parents;
+  llvm::SmallPtrSet<const VarDecl*, 20> Escaped;
+  OwningPtr<ReachableCode> reachableCode;
+  const CFGBlock *currentBlock;
+
+  enum DeadStoreKind { Standard, Enclosing, DeadIncrement, DeadInit };
+
+public:
+  DeadStoreObs(const CFG &cfg, ASTContext &ctx,
+               BugReporter& br, AnalysisDeclContext* ac, ParentMap& parents,
+               llvm::SmallPtrSet<const VarDecl*, 20> &escaped)
+    : cfg(cfg), Ctx(ctx), BR(br), AC(ac), Parents(parents),
+      Escaped(escaped), currentBlock(0) {}
+
+  virtual ~DeadStoreObs() {}
+
+  void Report(const VarDecl *V, DeadStoreKind dsk,
+              PathDiagnosticLocation L, SourceRange R) {
+    if (Escaped.count(V))
+      return;
+    
+    // Compute reachable blocks within the CFG for trivial cases
+    // where a bogus dead store can be reported because itself is unreachable.
+    if (!reachableCode.get()) {
+      reachableCode.reset(new ReachableCode(cfg));
+      reachableCode->computeReachableBlocks();
+    }
+    
+    if (!reachableCode->isReachable(currentBlock))
+      return;
+
+    SmallString<64> buf;
+    llvm::raw_svector_ostream os(buf);
+    const char *BugType = 0;
+
+    switch (dsk) {
+      case DeadInit:
+        BugType = "Dead initialization";
+        os << "Value stored to '" << *V
+           << "' during its initialization is never read";
+        break;
+
+      case DeadIncrement:
+        BugType = "Dead increment";
+      case Standard:
+        if (!BugType) BugType = "Dead assignment";
+        os << "Value stored to '" << *V << "' is never read";
+        break;
+
+      case Enclosing:
+        // Don't report issues in this case, e.g.: "if (x = foo())",
+        // where 'x' is unused later.  We have yet to see a case where 
+        // this is a real bug.
+        return;
+    }
+
+    BR.EmitBasicReport(AC->getDecl(), BugType, "Dead store", os.str(), L, R);
+  }
+
+  void CheckVarDecl(const VarDecl *VD, const Expr *Ex, const Expr *Val,
+                    DeadStoreKind dsk,
+                    const LiveVariables::LivenessValues &Live) {
+
+    if (!VD->hasLocalStorage())
+      return;
+    // Reference types confuse the dead stores checker.  Skip them
+    // for now.
+    if (VD->getType()->getAs<ReferenceType>())
+      return;
+
+    if (!Live.isLive(VD) && 
+        !(VD->getAttr<UnusedAttr>() || VD->getAttr<BlocksAttr>())) {
+
+      PathDiagnosticLocation ExLoc =
+        PathDiagnosticLocation::createBegin(Ex, BR.getSourceManager(), AC);
+      Report(VD, dsk, ExLoc, Val->getSourceRange());
+    }
+  }
+
+  void CheckDeclRef(const DeclRefExpr *DR, const Expr *Val, DeadStoreKind dsk,
+                    const LiveVariables::LivenessValues& Live) {
+    if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
+      CheckVarDecl(VD, DR, Val, dsk, Live);
+  }
+
+  bool isIncrement(VarDecl *VD, const BinaryOperator* B) {
+    if (B->isCompoundAssignmentOp())
+      return true;
+
+    const Expr *RHS = B->getRHS()->IgnoreParenCasts();
+    const BinaryOperator* BRHS = dyn_cast<BinaryOperator>(RHS);
+
+    if (!BRHS)
+      return false;
+
+    const DeclRefExpr *DR;
+
+    if ((DR = dyn_cast<DeclRefExpr>(BRHS->getLHS()->IgnoreParenCasts())))
+      if (DR->getDecl() == VD)
+        return true;
+
+    if ((DR = dyn_cast<DeclRefExpr>(BRHS->getRHS()->IgnoreParenCasts())))
+      if (DR->getDecl() == VD)
+        return true;
+
+    return false;
+  }
+
+  virtual void observeStmt(const Stmt *S, const CFGBlock *block,
+                           const LiveVariables::LivenessValues &Live) {
+
+    currentBlock = block;
+    
+    // Skip statements in macros.
+    if (S->getLocStart().isMacroID())
+      return;
+
+    // Only cover dead stores from regular assignments.  ++/-- dead stores
+    // have never flagged a real bug.
+    if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
+      if (!B->isAssignmentOp()) return; // Skip non-assignments.
+
+      if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(B->getLHS()))
+        if (VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+          // Special case: check for assigning null to a pointer.
+          //  This is a common form of defensive programming.
+          const Expr *RHS = LookThroughTransitiveAssignments(B->getRHS());
+          
+          QualType T = VD->getType();
+          if (T->isPointerType() || T->isObjCObjectPointerType()) {
+            if (RHS->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNull))
+              return;
+          }
+
+          RHS = RHS->IgnoreParenCasts();
+          // Special case: self-assignments.  These are often used to shut up
+          //  "unused variable" compiler warnings.
+          if (const DeclRefExpr *RhsDR = dyn_cast<DeclRefExpr>(RHS))
+            if (VD == dyn_cast<VarDecl>(RhsDR->getDecl()))
+              return;
+
+          // Otherwise, issue a warning.
+          DeadStoreKind dsk = Parents.isConsumedExpr(B)
+                              ? Enclosing
+                              : (isIncrement(VD,B) ? DeadIncrement : Standard);
+
+          CheckVarDecl(VD, DR, B->getRHS(), dsk, Live);
+        }
+    }
+    else if (const UnaryOperator* U = dyn_cast<UnaryOperator>(S)) {
+      if (!U->isIncrementOp() || U->isPrefix())
+        return;
+
+      const Stmt *parent = Parents.getParentIgnoreParenCasts(U);
+      if (!parent || !isa<ReturnStmt>(parent))
+        return;
+
+      const Expr *Ex = U->getSubExpr()->IgnoreParenCasts();
+
+      if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex))
+        CheckDeclRef(DR, U, DeadIncrement, Live);
+    }
+    else if (const DeclStmt *DS = dyn_cast<DeclStmt>(S))
+      // Iterate through the decls.  Warn if any initializers are complex
+      // expressions that are not live (never used).
+      for (DeclStmt::const_decl_iterator DI=DS->decl_begin(), DE=DS->decl_end();
+           DI != DE; ++DI) {
+
+        VarDecl *V = dyn_cast<VarDecl>(*DI);
+
+        if (!V)
+          continue;
+          
+        if (V->hasLocalStorage()) {          
+          // Reference types confuse the dead stores checker.  Skip them
+          // for now.
+          if (V->getType()->getAs<ReferenceType>())
+            return;
+            
+          if (const Expr *E = V->getInit()) {
+            while (const ExprWithCleanups *exprClean =
+                    dyn_cast<ExprWithCleanups>(E))
+              E = exprClean->getSubExpr();
+            
+            // Look through transitive assignments, e.g.:
+            // int x = y = 0;
+            E = LookThroughTransitiveAssignments(E);
+            
+            // Don't warn on C++ objects (yet) until we can show that their
+            // constructors/destructors don't have side effects.
+            if (isa<CXXConstructExpr>(E))
+              return;
+            
+            // A dead initialization is a variable that is dead after it
+            // is initialized.  We don't flag warnings for those variables
+            // marked 'unused'.
+            if (!Live.isLive(V) && V->getAttr<UnusedAttr>() == 0) {
+              // Special case: check for initializations with constants.
+              //
+              //  e.g. : int x = 0;
+              //
+              // If x is EVER assigned a new value later, don't issue
+              // a warning.  This is because such initialization can be
+              // due to defensive programming.
+              if (E->isEvaluatable(Ctx))
+                return;
+
+              if (const DeclRefExpr *DRE =
+                  dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
+                if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
+                  // Special case: check for initialization from constant
+                  //  variables.
+                  //
+                  //  e.g. extern const int MyConstant;
+                  //       int x = MyConstant;
+                  //
+                  if (VD->hasGlobalStorage() &&
+                      VD->getType().isConstQualified())
+                    return;
+                  // Special case: check for initialization from scalar
+                  //  parameters.  This is often a form of defensive
+                  //  programming.  Non-scalars are still an error since
+                  //  because it more likely represents an actual algorithmic
+                  //  bug.
+                  if (isa<ParmVarDecl>(VD) && VD->getType()->isScalarType())
+                    return;
+                }
+
+              PathDiagnosticLocation Loc =
+                PathDiagnosticLocation::create(V, BR.getSourceManager());
+              Report(V, DeadInit, Loc, E->getSourceRange());
+            }
+          }
+        }
+      }
+  }
+};
+
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Driver function to invoke the Dead-Stores checker on a CFG.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class FindEscaped : public CFGRecStmtDeclVisitor<FindEscaped>{
+  CFG *cfg;
+public:
+  FindEscaped(CFG *c) : cfg(c) {}
+
+  CFG& getCFG() { return *cfg; }
+
+  llvm::SmallPtrSet<const VarDecl*, 20> Escaped;
+
+  void VisitUnaryOperator(UnaryOperator* U) {
+    // Check for '&'.  Any VarDecl whose value has its address-taken we
+    // treat as escaped.
+    Expr *E = U->getSubExpr()->IgnoreParenCasts();
+    if (U->getOpcode() == UO_AddrOf)
+      if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E))
+        if (VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+          Escaped.insert(VD);
+          return;
+        }
+    Visit(E);
+  }
+};
+} // end anonymous namespace
+
+
+//===----------------------------------------------------------------------===//
+// DeadStoresChecker
+//===----------------------------------------------------------------------===//
+
+namespace {
+class DeadStoresChecker : public Checker<check::ASTCodeBody> {
+public:
+  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
+                        BugReporter &BR) const {
+    if (LiveVariables *L = mgr.getAnalysis<LiveVariables>(D)) {
+      CFG &cfg = *mgr.getCFG(D);
+      AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D);
+      ParentMap &pmap = mgr.getParentMap(D);
+      FindEscaped FS(&cfg);
+      FS.getCFG().VisitBlockStmts(FS);
+      DeadStoreObs A(cfg, BR.getContext(), BR, AC, pmap, FS.Escaped);
+      L->runOnAllBlocks(A);
+    }
+  }
+};
+}
+
+void ento::registerDeadStoresChecker(CheckerManager &mgr) {
+  mgr.registerChecker<DeadStoresChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp b/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
new file mode 100644
index 0000000..34053cd
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
@@ -0,0 +1,146 @@
+//==- DebugCheckers.cpp - Debugging Checkers ---------------------*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines a checkers that display debugging information.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "clang/Analysis/Analyses/LiveVariables.h"
+#include "clang/Analysis/Analyses/Dominators.h"
+#include "clang/Analysis/CallGraph.h"
+#include "llvm/Support/Process.h"
+
+using namespace clang;
+using namespace ento;
+
+//===----------------------------------------------------------------------===//
+// DominatorsTreeDumper
+//===----------------------------------------------------------------------===//
+
+namespace {
+class DominatorsTreeDumper : public Checker<check::ASTCodeBody> {
+public:
+  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
+                        BugReporter &BR) const {
+    if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
+      DominatorTree dom;
+      dom.buildDominatorTree(*AC);
+      dom.dump();
+    }
+  }
+};
+}
+
+void ento::registerDominatorsTreeDumper(CheckerManager &mgr) {
+  mgr.registerChecker<DominatorsTreeDumper>();
+}
+
+//===----------------------------------------------------------------------===//
+// LiveVariablesDumper
+//===----------------------------------------------------------------------===//
+
+namespace {
+class LiveVariablesDumper : public Checker<check::ASTCodeBody> {
+public:
+  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
+                        BugReporter &BR) const {
+    if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) {
+      L->dumpBlockLiveness(mgr.getSourceManager());
+    }
+  }
+};
+}
+
+void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
+  mgr.registerChecker<LiveVariablesDumper>();
+}
+
+//===----------------------------------------------------------------------===//
+// CFGViewer
+//===----------------------------------------------------------------------===//
+
+namespace {
+class CFGViewer : public Checker<check::ASTCodeBody> {
+public:
+  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
+                        BugReporter &BR) const {
+    if (CFG *cfg = mgr.getCFG(D)) {
+      cfg->viewCFG(mgr.getLangOpts());
+    }
+  }
+};
+}
+
+void ento::registerCFGViewer(CheckerManager &mgr) {
+  mgr.registerChecker<CFGViewer>();
+}
+
+//===----------------------------------------------------------------------===//
+// CFGDumper
+//===----------------------------------------------------------------------===//
+
+namespace {
+class CFGDumper : public Checker<check::ASTCodeBody> {
+public:
+  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
+                        BugReporter &BR) const {
+    if (CFG *cfg = mgr.getCFG(D)) {
+      cfg->dump(mgr.getLangOpts(),
+                llvm::sys::Process::StandardErrHasColors());
+    }
+  }
+};
+}
+
+void ento::registerCFGDumper(CheckerManager &mgr) {
+  mgr.registerChecker<CFGDumper>();
+}
+
+//===----------------------------------------------------------------------===//
+// CallGraphViewer
+//===----------------------------------------------------------------------===//
+
+namespace {
+class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
+public:
+  void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
+                    BugReporter &BR) const {
+    CallGraph CG;
+    CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
+    CG.viewGraph();
+  }
+};
+}
+
+void ento::registerCallGraphViewer(CheckerManager &mgr) {
+  mgr.registerChecker<CallGraphViewer>();
+}
+
+//===----------------------------------------------------------------------===//
+// CallGraphDumper
+//===----------------------------------------------------------------------===//
+
+namespace {
+class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
+public:
+  void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
+                    BugReporter &BR) const {
+    CallGraph CG;
+    CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
+    CG.dump();
+  }
+};
+}
+
+void ento::registerCallGraphDumper(CheckerManager &mgr) {
+  mgr.registerChecker<CallGraphDumper>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
new file mode 100644
index 0000000..81a2745
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
@@ -0,0 +1,216 @@
+//== 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 ExprEngine that performs
+// checks for null pointers at loads and stores.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class DereferenceChecker
+    : public Checker< check::Location,
+                        EventDispatcher<ImplicitNullDerefEvent> > {
+  mutable OwningPtr<BuiltinBug> BT_null;
+  mutable OwningPtr<BuiltinBug> BT_undef;
+
+public:
+  void checkLocation(SVal location, bool isLoad, const Stmt* S,
+                     CheckerContext &C) const;
+
+  static const MemRegion *AddDerefSource(raw_ostream &os,
+                             SmallVectorImpl<SourceRange> &Ranges,
+                             const Expr *Ex, const ProgramState *state,
+                             const LocationContext *LCtx,
+                             bool loadedFrom = false);
+};
+} // end anonymous namespace
+
+const MemRegion *
+DereferenceChecker::AddDerefSource(raw_ostream &os,
+                                   SmallVectorImpl<SourceRange> &Ranges,
+                                   const Expr *Ex,
+                                   const ProgramState *state,
+                                   const LocationContext *LCtx,
+                                   bool loadedFrom) {
+  Ex = Ex->IgnoreParenLValueCasts();
+  const MemRegion *sourceR = 0;
+  switch (Ex->getStmtClass()) {
+    default:
+      break;
+    case Stmt::DeclRefExprClass: {
+      const DeclRefExpr *DR = cast<DeclRefExpr>(Ex);
+      if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+        os << " (" << (loadedFrom ? "loaded from" : "from")
+           << " variable '" <<  VD->getName() << "')";
+        Ranges.push_back(DR->getSourceRange());
+        sourceR = state->getLValue(VD, LCtx).getAsRegion();
+      }
+      break;
+    }
+    case Stmt::MemberExprClass: {
+      const MemberExpr *ME = cast<MemberExpr>(Ex);
+      os << " (" << (loadedFrom ? "loaded from" : "via")
+         << " field '" << ME->getMemberNameInfo() << "')";
+      SourceLocation L = ME->getMemberLoc();
+      Ranges.push_back(SourceRange(L, L));
+      break;
+    }
+  }
+  return sourceR;
+}
+
+void DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S,
+                                       CheckerContext &C) const {
+  // Check for dereference of an undefined value.
+  if (l.isUndef()) {
+    if (ExplodedNode *N = C.generateSink()) {
+      if (!BT_undef)
+        BT_undef.reset(new BuiltinBug("Dereference of undefined pointer value"));
+
+      BugReport *report =
+        new BugReport(*BT_undef, BT_undef->getDescription(), N);
+      report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
+                                        bugreporter::GetDerefExpr(N), report));
+      C.EmitReport(report);
+    }
+    return;
+  }
+
+  DefinedOrUnknownSVal location = cast<DefinedOrUnknownSVal>(l);
+
+  // Check for null dereferences.
+  if (!isa<Loc>(location))
+    return;
+
+  ProgramStateRef state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
+  ProgramStateRef notNullState, nullState;
+  llvm::tie(notNullState, nullState) = state->assume(location);
+
+  // The explicit NULL case.
+  if (nullState) {
+    if (!notNullState) {
+      // Generate an error node.
+      ExplodedNode *N = C.generateSink(nullState);
+      if (!N)
+        return;
+
+      // We know that 'location' cannot be non-null.  This is what
+      // we call an "explicit" null dereference.
+      if (!BT_null)
+        BT_null.reset(new BuiltinBug("Dereference of null pointer"));
+
+      SmallString<100> buf;
+      SmallVector<SourceRange, 2> Ranges;
+      
+      // Walk through lvalue casts to get the original expression
+      // that syntactically caused the load.
+      if (const Expr *expr = dyn_cast<Expr>(S))
+        S = expr->IgnoreParenLValueCasts();
+      
+      const MemRegion *sourceR = 0;
+
+      switch (S->getStmtClass()) {
+        case Stmt::ArraySubscriptExprClass: {
+          llvm::raw_svector_ostream os(buf);
+          os << "Array access";
+          const ArraySubscriptExpr *AE = cast<ArraySubscriptExpr>(S);
+          sourceR =
+            AddDerefSource(os, Ranges, AE->getBase()->IgnoreParenCasts(),
+                           state.getPtr(), LCtx);
+          os << " results in a null pointer dereference";
+          break;
+        }
+        case Stmt::UnaryOperatorClass: {
+          llvm::raw_svector_ostream os(buf);
+          os << "Dereference of null pointer";
+          const UnaryOperator *U = cast<UnaryOperator>(S);
+          sourceR =
+            AddDerefSource(os, Ranges, U->getSubExpr()->IgnoreParens(),
+                           state.getPtr(), LCtx, true);
+          break;
+        }
+        case Stmt::MemberExprClass: {
+          const MemberExpr *M = cast<MemberExpr>(S);
+          if (M->isArrow()) {
+            llvm::raw_svector_ostream os(buf);
+            os << "Access to field '" << M->getMemberNameInfo()
+               << "' results in a dereference of a null pointer";
+            sourceR =
+              AddDerefSource(os, Ranges, M->getBase()->IgnoreParenCasts(),
+                             state.getPtr(), LCtx, true);
+          }
+          break;
+        }
+        case Stmt::ObjCIvarRefExprClass: {
+          const ObjCIvarRefExpr *IV = cast<ObjCIvarRefExpr>(S);
+          if (const DeclRefExpr *DR =
+              dyn_cast<DeclRefExpr>(IV->getBase()->IgnoreParenCasts())) {
+            if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+              llvm::raw_svector_ostream os(buf);
+              os << "Instance variable access (via '" << VD->getName()
+                 << "') results in a null pointer dereference";
+            }
+          }
+          Ranges.push_back(IV->getSourceRange());
+          break;
+        }
+        default:
+          break;
+      }
+
+      BugReport *report =
+        new BugReport(*BT_null,
+                              buf.empty() ? BT_null->getDescription():buf.str(),
+                              N);
+
+      report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
+                                        bugreporter::GetDerefExpr(N), report));
+
+      for (SmallVectorImpl<SourceRange>::iterator
+            I = Ranges.begin(), E = Ranges.end(); I!=E; ++I)
+        report->addRange(*I);
+
+      if (sourceR) {
+        report->markInteresting(sourceR);
+        report->markInteresting(state->getRawSVal(loc::MemRegionVal(sourceR)));
+      }
+
+      C.EmitReport(report);
+      return;
+    }
+    else {
+      // Otherwise, we have the case where the location could either be
+      // null or not-null.  Record the error node as an "implicit" null
+      // dereference.
+      if (ExplodedNode *N = C.generateSink(nullState)) {
+        ImplicitNullDerefEvent event = { l, isLoad, N, &C.getBugReporter() };
+        dispatchEvent(event);
+      }
+    }
+  }
+
+  // From this point forward, we know that the location is not null.
+  C.addTransition(notNullState);
+}
+
+void ento::registerDereferenceChecker(CheckerManager &mgr) {
+  mgr.registerChecker<DereferenceChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
new file mode 100644
index 0000000..2627f0c
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
@@ -0,0 +1,96 @@
+//== 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 ExprEngine that performs
+// checks for division by zeros.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class DivZeroChecker : public Checker< check::PreStmt<BinaryOperator> > {
+  mutable OwningPtr<BuiltinBug> BT;
+  void reportBug(const char *Msg,
+                 ProgramStateRef StateZero,
+                 CheckerContext &C) const ;
+public:
+  void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
+};  
+} // end anonymous namespace
+
+void DivZeroChecker::reportBug(const char *Msg,
+                               ProgramStateRef StateZero,
+                               CheckerContext &C) const {
+  if (ExplodedNode *N = C.generateSink(StateZero)) {
+    if (!BT)
+      BT.reset(new BuiltinBug("Division by zero"));
+
+    BugReport *R =
+      new BugReport(*BT, Msg, N);
+
+    R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
+                                 bugreporter::GetDenomExpr(N), R));
+    C.EmitReport(R);
+  }
+}
+
+void DivZeroChecker::checkPreStmt(const BinaryOperator *B,
+                                  CheckerContext &C) const {
+  BinaryOperator::Opcode Op = B->getOpcode();
+  if (Op != BO_Div &&
+      Op != BO_Rem &&
+      Op != BO_DivAssign &&
+      Op != BO_RemAssign)
+    return;
+
+  if (!B->getRHS()->getType()->isIntegerType() ||
+      !B->getRHS()->getType()->isScalarType())
+    return;
+
+  SVal Denom = C.getState()->getSVal(B->getRHS(), C.getLocationContext());
+  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();
+  ProgramStateRef stateNotZero, stateZero;
+  llvm::tie(stateNotZero, stateZero) = CM.assumeDual(C.getState(), *DV);
+
+  if (!stateNotZero) {
+    assert(stateZero);
+    reportBug("Division by zero", stateZero, C);
+    return;
+  }
+
+  bool TaintedD = C.getState()->isTainted(*DV);
+  if ((stateNotZero && stateZero && TaintedD)) {
+    reportBug("Division by a tainted value, possibly zero", stateZero, C);
+    return;
+  }
+
+  // If we get here, then the denom should not be zero. We abandon the implicit
+  // zero denom case for now.
+  C.addTransition(stateNotZero);
+}
+
+void ento::registerDivZeroChecker(CheckerManager &mgr) {
+  mgr.registerChecker<DivZeroChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
new file mode 100644
index 0000000..a1f2f3b
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
@@ -0,0 +1,67 @@
+//=== FixedAddressChecker.cpp - Fixed address usage checker ----*- C++ -*--===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This files defines FixedAddressChecker, a builtin checker that checks for
+// assignment of a fixed address to a pointer.
+// This check corresponds to CWE-587.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class FixedAddressChecker 
+  : public Checker< check::PreStmt<BinaryOperator> > {
+  mutable OwningPtr<BuiltinBug> BT;
+
+public:
+  void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
+};
+}
+
+void FixedAddressChecker::checkPreStmt(const BinaryOperator *B,
+                                       CheckerContext &C) const {
+  // Using a fixed address is not portable because that address will probably
+  // not be valid in all environments or platforms.
+
+  if (B->getOpcode() != BO_Assign)
+    return;
+
+  QualType T = B->getType();
+  if (!T->isPointerType())
+    return;
+
+  ProgramStateRef state = C.getState();
+  SVal RV = state->getSVal(B->getRHS(), C.getLocationContext());
+
+  if (!RV.isConstant() || RV.isZeroConstant())
+    return;
+
+  if (ExplodedNode *N = C.addTransition()) {
+    if (!BT)
+      BT.reset(new BuiltinBug("Use fixed address", 
+                          "Using a fixed address is not portable because that "
+                          "address will probably not be valid in all "
+                          "environments or platforms."));
+    BugReport *R = new BugReport(*BT, BT->getDescription(), N);
+    R->addRange(B->getRHS()->getSourceRange());
+    C.EmitReport(R);
+  }
+}
+
+void ento::registerFixedAddressChecker(CheckerManager &mgr) {
+  mgr.registerChecker<FixedAddressChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
new file mode 100644
index 0000000..135b81d
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -0,0 +1,740 @@
+//== GenericTaintChecker.cpp ----------------------------------- -*- C++ -*--=//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This checker defines the attack surface for generic taint propagation.
+//
+// The taint information produced by it might be useful to other checkers. For
+// example, checkers should report errors which involve tainted data more
+// aggressively, even if the involved symbols are under constrained.
+//
+//===----------------------------------------------------------------------===//
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/Basic/Builtins.h"
+#include <climits>
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class GenericTaintChecker : public Checker< check::PostStmt<CallExpr>,
+                                            check::PreStmt<CallExpr> > {
+public:
+  static void *getTag() { static int Tag; return &Tag; }
+
+  void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
+  void checkPostStmt(const DeclRefExpr *DRE, CheckerContext &C) const;
+
+  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
+
+private:
+  static const unsigned InvalidArgIndex = UINT_MAX;
+  /// Denotes the return vale.
+  static const unsigned ReturnValueIndex = UINT_MAX - 1;
+
+  mutable OwningPtr<BugType> BT;
+  inline void initBugType() const {
+    if (!BT)
+      BT.reset(new BugType("Use of Untrusted Data", "Untrusted Data"));
+  }
+
+  /// \brief Catch taint related bugs. Check if tainted data is passed to a
+  /// system call etc.
+  bool checkPre(const CallExpr *CE, CheckerContext &C) const;
+
+  /// \brief Add taint sources on a pre-visit.
+  void addSourcesPre(const CallExpr *CE, CheckerContext &C) const;
+
+  /// \brief Propagate taint generated at pre-visit.
+  bool propagateFromPre(const CallExpr *CE, CheckerContext &C) const;
+
+  /// \brief Add taint sources on a post visit.
+  void addSourcesPost(const CallExpr *CE, CheckerContext &C) const;
+
+  /// Check if the region the expression evaluates to is the standard input,
+  /// and thus, is tainted.
+  static bool isStdin(const Expr *E, CheckerContext &C);
+
+  /// \brief Given a pointer argument, get the symbol of the value it contains
+  /// (points to).
+  static SymbolRef getPointedToSymbol(CheckerContext &C, const Expr *Arg);
+
+  /// Functions defining the attack surface.
+  typedef ProgramStateRef (GenericTaintChecker::*FnCheck)(const CallExpr *,
+                                                       CheckerContext &C) const;
+  ProgramStateRef postScanf(const CallExpr *CE, CheckerContext &C) const;
+  ProgramStateRef postSocket(const CallExpr *CE, CheckerContext &C) const;
+  ProgramStateRef postRetTaint(const CallExpr *CE, CheckerContext &C) const;
+
+  /// Taint the scanned input if the file is tainted.
+  ProgramStateRef preFscanf(const CallExpr *CE, CheckerContext &C) const;
+
+  /// Check for CWE-134: Uncontrolled Format String.
+  static const char MsgUncontrolledFormatString[];
+  bool checkUncontrolledFormatString(const CallExpr *CE,
+                                     CheckerContext &C) const;
+
+  /// Check for:
+  /// CERT/STR02-C. "Sanitize data passed to complex subsystems"
+  /// CWE-78, "Failure to Sanitize Data into an OS Command"
+  static const char MsgSanitizeSystemArgs[];
+  bool checkSystemCall(const CallExpr *CE, StringRef Name,
+                       CheckerContext &C) const;
+
+  /// Check if tainted data is used as a buffer size ins strn.. functions,
+  /// and allocators.
+  static const char MsgTaintedBufferSize[];
+  bool checkTaintedBufferSize(const CallExpr *CE, const FunctionDecl *FDecl,
+                              CheckerContext &C) const;
+
+  /// Generate a report if the expression is tainted or points to tainted data.
+  bool generateReportIfTainted(const Expr *E, const char Msg[],
+                               CheckerContext &C) const;
+                               
+  
+  typedef llvm::SmallVector<unsigned, 2> ArgVector;
+
+  /// \brief A struct used to specify taint propagation rules for a function.
+  ///
+  /// If any of the possible taint source arguments is tainted, all of the
+  /// destination arguments should also be tainted. Use InvalidArgIndex in the
+  /// src list to specify that all of the arguments can introduce taint. Use
+  /// InvalidArgIndex in the dst arguments to signify that all the non-const
+  /// pointer and reference arguments might be tainted on return. If
+  /// ReturnValueIndex is added to the dst list, the return value will be
+  /// tainted.
+  struct TaintPropagationRule {
+    /// List of arguments which can be taint sources and should be checked.
+    ArgVector SrcArgs;
+    /// List of arguments which should be tainted on function return.
+    ArgVector DstArgs;
+    // TODO: Check if using other data structures would be more optimal.
+
+    TaintPropagationRule() {}
+
+    TaintPropagationRule(unsigned SArg,
+                         unsigned DArg, bool TaintRet = false) {
+      SrcArgs.push_back(SArg);
+      DstArgs.push_back(DArg);
+      if (TaintRet)
+        DstArgs.push_back(ReturnValueIndex);
+    }
+
+    TaintPropagationRule(unsigned SArg1, unsigned SArg2,
+                         unsigned DArg, bool TaintRet = false) {
+      SrcArgs.push_back(SArg1);
+      SrcArgs.push_back(SArg2);
+      DstArgs.push_back(DArg);
+      if (TaintRet)
+        DstArgs.push_back(ReturnValueIndex);
+    }
+
+    /// Get the propagation rule for a given function.
+    static TaintPropagationRule
+      getTaintPropagationRule(const FunctionDecl *FDecl,
+                              StringRef Name,
+                              CheckerContext &C);
+
+    inline void addSrcArg(unsigned A) { SrcArgs.push_back(A); }
+    inline void addDstArg(unsigned A)  { DstArgs.push_back(A); }
+
+    inline bool isNull() const { return SrcArgs.empty(); }
+
+    inline bool isDestinationArgument(unsigned ArgNum) const {
+      return (std::find(DstArgs.begin(),
+                        DstArgs.end(), ArgNum) != DstArgs.end());
+    }
+
+    static inline bool isTaintedOrPointsToTainted(const Expr *E,
+                                                  ProgramStateRef State,
+                                                  CheckerContext &C) {
+      return (State->isTainted(E, C.getLocationContext()) || isStdin(E, C) ||
+              (E->getType().getTypePtr()->isPointerType() &&
+               State->isTainted(getPointedToSymbol(C, E))));
+    }
+
+    /// \brief Pre-process a function which propagates taint according to the
+    /// taint rule.
+    ProgramStateRef process(const CallExpr *CE, CheckerContext &C) const;
+
+  };
+};
+
+const unsigned GenericTaintChecker::ReturnValueIndex;
+const unsigned GenericTaintChecker::InvalidArgIndex;
+
+const char GenericTaintChecker::MsgUncontrolledFormatString[] =
+  "Untrusted data is used as a format string "
+  "(CWE-134: Uncontrolled Format String)";
+
+const char GenericTaintChecker::MsgSanitizeSystemArgs[] =
+  "Untrusted data is passed to a system call "
+  "(CERT/STR02-C. Sanitize data passed to complex subsystems)";
+
+const char GenericTaintChecker::MsgTaintedBufferSize[] =
+  "Untrusted data is used to specify the buffer size "
+  "(CERT/STR31-C. Guarantee that storage for strings has sufficient space for "
+  "character data and the null terminator)";
+
+} // end of anonymous namespace
+
+/// A set which is used to pass information from call pre-visit instruction
+/// to the call post-visit. The values are unsigned integers, which are either
+/// ReturnValueIndex, or indexes of the pointer/reference argument, which
+/// points to data, which should be tainted on return.
+namespace { struct TaintArgsOnPostVisit{}; }
+namespace clang { namespace ento {
+template<> struct ProgramStateTrait<TaintArgsOnPostVisit>
+    :  public ProgramStatePartialTrait<llvm::ImmutableSet<unsigned> > {
+  static void *GDMIndex() { return GenericTaintChecker::getTag(); }
+};
+}}
+
+GenericTaintChecker::TaintPropagationRule
+GenericTaintChecker::TaintPropagationRule::getTaintPropagationRule(
+                                                     const FunctionDecl *FDecl,
+                                                     StringRef Name,
+                                                     CheckerContext &C) {
+  // TODO: Currently, we might loose precision here: we always mark a return
+  // value as tainted even if it's just a pointer, pointing to tainted data.
+
+  // Check for exact name match for functions without builtin substitutes.
+  TaintPropagationRule Rule = llvm::StringSwitch<TaintPropagationRule>(Name)
+    .Case("atoi", TaintPropagationRule(0, ReturnValueIndex))
+    .Case("atol", TaintPropagationRule(0, ReturnValueIndex))
+    .Case("atoll", TaintPropagationRule(0, ReturnValueIndex))
+    .Case("getc", TaintPropagationRule(0, ReturnValueIndex))
+    .Case("fgetc", TaintPropagationRule(0, ReturnValueIndex))
+    .Case("getc_unlocked", TaintPropagationRule(0, ReturnValueIndex))
+    .Case("getw", TaintPropagationRule(0, ReturnValueIndex))
+    .Case("toupper", TaintPropagationRule(0, ReturnValueIndex))
+    .Case("tolower", TaintPropagationRule(0, ReturnValueIndex))
+    .Case("strchr", TaintPropagationRule(0, ReturnValueIndex))
+    .Case("strrchr", TaintPropagationRule(0, ReturnValueIndex))
+    .Case("read", TaintPropagationRule(0, 2, 1, true))
+    .Case("pread", TaintPropagationRule(InvalidArgIndex, 1, true))
+    .Case("gets", TaintPropagationRule(InvalidArgIndex, 0, true))
+    .Case("fgets", TaintPropagationRule(2, 0, true))
+    .Case("getline", TaintPropagationRule(2, 0))
+    .Case("getdelim", TaintPropagationRule(3, 0))
+    .Case("fgetln", TaintPropagationRule(0, ReturnValueIndex))
+    .Default(TaintPropagationRule());
+
+  if (!Rule.isNull())
+    return Rule;
+
+  // Check if it's one of the memory setting/copying functions.
+  // This check is specialized but faster then calling isCLibraryFunction.
+  unsigned BId = 0;
+  if ( (BId = FDecl->getMemoryFunctionKind()) )
+    switch(BId) {
+    case Builtin::BImemcpy:
+    case Builtin::BImemmove:
+    case Builtin::BIstrncpy:
+    case Builtin::BIstrncat:
+      return TaintPropagationRule(1, 2, 0, true);
+    case Builtin::BIstrlcpy:
+    case Builtin::BIstrlcat:
+      return TaintPropagationRule(1, 2, 0, false);
+    case Builtin::BIstrndup:
+      return TaintPropagationRule(0, 1, ReturnValueIndex);
+
+    default:
+      break;
+    };
+
+  // Process all other functions which could be defined as builtins.
+  if (Rule.isNull()) {
+    if (C.isCLibraryFunction(FDecl, "snprintf") ||
+        C.isCLibraryFunction(FDecl, "sprintf"))
+      return TaintPropagationRule(InvalidArgIndex, 0, true);
+    else if (C.isCLibraryFunction(FDecl, "strcpy") ||
+             C.isCLibraryFunction(FDecl, "stpcpy") ||
+             C.isCLibraryFunction(FDecl, "strcat"))
+      return TaintPropagationRule(1, 0, true);
+    else if (C.isCLibraryFunction(FDecl, "bcopy"))
+      return TaintPropagationRule(0, 2, 1, false);
+    else if (C.isCLibraryFunction(FDecl, "strdup") ||
+             C.isCLibraryFunction(FDecl, "strdupa"))
+      return TaintPropagationRule(0, ReturnValueIndex);
+    else if (C.isCLibraryFunction(FDecl, "wcsdup"))
+      return TaintPropagationRule(0, ReturnValueIndex);
+  }
+
+  // Skipping the following functions, since they might be used for cleansing
+  // or smart memory copy:
+  // - memccpy - copying untill hitting a special character.
+
+  return TaintPropagationRule();
+}
+
+void GenericTaintChecker::checkPreStmt(const CallExpr *CE,
+                                       CheckerContext &C) const {
+  // Check for errors first.
+  if (checkPre(CE, C))
+    return;
+
+  // Add taint second.
+  addSourcesPre(CE, C);
+}
+
+void GenericTaintChecker::checkPostStmt(const CallExpr *CE,
+                                        CheckerContext &C) const {
+  if (propagateFromPre(CE, C))
+    return;
+  addSourcesPost(CE, C);
+}
+
+void GenericTaintChecker::addSourcesPre(const CallExpr *CE,
+                                        CheckerContext &C) const {
+  ProgramStateRef State = 0;
+  const FunctionDecl *FDecl = C.getCalleeDecl(CE);
+  StringRef Name = C.getCalleeName(FDecl);
+  if (Name.empty())
+    return;
+
+  // First, try generating a propagation rule for this function.
+  TaintPropagationRule Rule =
+    TaintPropagationRule::getTaintPropagationRule(FDecl, Name, C);
+  if (!Rule.isNull()) {
+    State = Rule.process(CE, C);
+    if (!State)
+      return;
+    C.addTransition(State);
+    return;
+  }
+
+  // Otherwise, check if we have custom pre-processing implemented.
+  FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
+    .Case("fscanf", &GenericTaintChecker::preFscanf)
+    .Default(0);
+  // Check and evaluate the call.
+  if (evalFunction)
+    State = (this->*evalFunction)(CE, C);
+  if (!State)
+    return;
+  C.addTransition(State);
+
+}
+
+bool GenericTaintChecker::propagateFromPre(const CallExpr *CE,
+                                           CheckerContext &C) const {
+  ProgramStateRef State = C.getState();
+
+  // Depending on what was tainted at pre-visit, we determined a set of
+  // arguments which should be tainted after the function returns. These are
+  // stored in the state as TaintArgsOnPostVisit set.
+  llvm::ImmutableSet<unsigned> TaintArgs = State->get<TaintArgsOnPostVisit>();
+  if (TaintArgs.isEmpty())
+    return false;
+
+  for (llvm::ImmutableSet<unsigned>::iterator
+         I = TaintArgs.begin(), E = TaintArgs.end(); I != E; ++I) {
+    unsigned ArgNum  = *I;
+
+    // Special handling for the tainted return value.
+    if (ArgNum == ReturnValueIndex) {
+      State = State->addTaint(CE, C.getLocationContext());
+      continue;
+    }
+
+    // The arguments are pointer arguments. The data they are pointing at is
+    // tainted after the call.
+    if (CE->getNumArgs() < (ArgNum + 1))
+      return false;
+    const Expr* Arg = CE->getArg(ArgNum);
+    SymbolRef Sym = getPointedToSymbol(C, Arg);
+    if (Sym)
+      State = State->addTaint(Sym);
+  }
+
+  // Clear up the taint info from the state.
+  State = State->remove<TaintArgsOnPostVisit>();
+
+  if (State != C.getState()) {
+    C.addTransition(State);
+    return true;
+  }
+  return false;
+}
+
+void GenericTaintChecker::addSourcesPost(const CallExpr *CE,
+                                         CheckerContext &C) const {
+  // Define the attack surface.
+  // Set the evaluation function by switching on the callee name.
+  StringRef Name = C.getCalleeName(CE);
+  if (Name.empty())
+    return;
+  FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
+    .Case("scanf", &GenericTaintChecker::postScanf)
+    // TODO: Add support for vfscanf & family.
+    .Case("getchar", &GenericTaintChecker::postRetTaint)
+    .Case("getchar_unlocked", &GenericTaintChecker::postRetTaint)
+    .Case("getenv", &GenericTaintChecker::postRetTaint)
+    .Case("fopen", &GenericTaintChecker::postRetTaint)
+    .Case("fdopen", &GenericTaintChecker::postRetTaint)
+    .Case("freopen", &GenericTaintChecker::postRetTaint)
+    .Case("getch", &GenericTaintChecker::postRetTaint)
+    .Case("wgetch", &GenericTaintChecker::postRetTaint)
+    .Case("socket", &GenericTaintChecker::postSocket)
+    .Default(0);
+
+  // If the callee isn't defined, it is not of security concern.
+  // Check and evaluate the call.
+  ProgramStateRef State = 0;
+  if (evalFunction)
+    State = (this->*evalFunction)(CE, C);
+  if (!State)
+    return;
+
+  C.addTransition(State);
+}
+
+bool GenericTaintChecker::checkPre(const CallExpr *CE, CheckerContext &C) const{
+
+  if (checkUncontrolledFormatString(CE, C))
+    return true;
+
+  const FunctionDecl *FDecl = C.getCalleeDecl(CE);
+  StringRef Name = C.getCalleeName(FDecl);
+  if (Name.empty())
+    return false;
+
+  if (checkSystemCall(CE, Name, C))
+    return true;
+
+  if (checkTaintedBufferSize(CE, FDecl, C))
+    return true;
+
+  return false;
+}
+
+SymbolRef GenericTaintChecker::getPointedToSymbol(CheckerContext &C,
+                                                  const Expr* Arg) {
+  ProgramStateRef State = C.getState();
+  SVal AddrVal = State->getSVal(Arg->IgnoreParens(), C.getLocationContext());
+  if (AddrVal.isUnknownOrUndef())
+    return 0;
+
+  Loc *AddrLoc = dyn_cast<Loc>(&AddrVal);
+  if (!AddrLoc)
+    return 0;
+
+  const PointerType *ArgTy =
+    dyn_cast<PointerType>(Arg->getType().getCanonicalType().getTypePtr());
+  SVal Val = State->getSVal(*AddrLoc,
+                            ArgTy ? ArgTy->getPointeeType(): QualType());
+  return Val.getAsSymbol();
+}
+
+ProgramStateRef 
+GenericTaintChecker::TaintPropagationRule::process(const CallExpr *CE,
+                                                   CheckerContext &C) const {
+  ProgramStateRef State = C.getState();
+
+  // Check for taint in arguments.
+  bool IsTainted = false;
+  for (ArgVector::const_iterator I = SrcArgs.begin(),
+                                 E = SrcArgs.end(); I != E; ++I) {
+    unsigned ArgNum = *I;
+
+    if (ArgNum == InvalidArgIndex) {
+      // Check if any of the arguments is tainted, but skip the
+      // destination arguments.
+      for (unsigned int i = 0; i < CE->getNumArgs(); ++i) {
+        if (isDestinationArgument(i))
+          continue;
+        if ((IsTainted = isTaintedOrPointsToTainted(CE->getArg(i), State, C)))
+          break;
+      }
+      break;
+    }
+
+    if (CE->getNumArgs() < (ArgNum + 1))
+      return State;
+    if ((IsTainted = isTaintedOrPointsToTainted(CE->getArg(ArgNum), State, C)))
+      break;
+  }
+  if (!IsTainted)
+    return State;
+
+  // Mark the arguments which should be tainted after the function returns.
+  for (ArgVector::const_iterator I = DstArgs.begin(),
+                                 E = DstArgs.end(); I != E; ++I) {
+    unsigned ArgNum = *I;
+
+    // Should we mark all arguments as tainted?
+    if (ArgNum == InvalidArgIndex) {
+      // For all pointer and references that were passed in:
+      //   If they are not pointing to const data, mark data as tainted.
+      //   TODO: So far we are just going one level down; ideally we'd need to
+      //         recurse here.
+      for (unsigned int i = 0; i < CE->getNumArgs(); ++i) {
+        const Expr *Arg = CE->getArg(i);
+        // Process pointer argument.
+        const Type *ArgTy = Arg->getType().getTypePtr();
+        QualType PType = ArgTy->getPointeeType();
+        if ((!PType.isNull() && !PType.isConstQualified())
+            || (ArgTy->isReferenceType() && !Arg->getType().isConstQualified()))
+          State = State->add<TaintArgsOnPostVisit>(i);
+      }
+      continue;
+    }
+
+    // Should mark the return value?
+    if (ArgNum == ReturnValueIndex) {
+      State = State->add<TaintArgsOnPostVisit>(ReturnValueIndex);
+      continue;
+    }
+
+    // Mark the given argument.
+    assert(ArgNum < CE->getNumArgs());
+    State = State->add<TaintArgsOnPostVisit>(ArgNum);
+  }
+
+  return State;
+}
+
+
+// If argument 0 (file descriptor) is tainted, all arguments except for arg 0
+// and arg 1 should get taint.
+ProgramStateRef GenericTaintChecker::preFscanf(const CallExpr *CE,
+                                                   CheckerContext &C) const {
+  assert(CE->getNumArgs() >= 2);
+  ProgramStateRef State = C.getState();
+
+  // Check is the file descriptor is tainted.
+  if (State->isTainted(CE->getArg(0), C.getLocationContext()) ||
+      isStdin(CE->getArg(0), C)) {
+    // All arguments except for the first two should get taint.
+    for (unsigned int i = 2; i < CE->getNumArgs(); ++i)
+        State = State->add<TaintArgsOnPostVisit>(i);
+    return State;
+  }
+
+  return 0;
+}
+
+
+// If argument 0(protocol domain) is network, the return value should get taint.
+ProgramStateRef GenericTaintChecker::postSocket(const CallExpr *CE,
+                                                CheckerContext &C) const {
+  ProgramStateRef State = C.getState();
+  if (CE->getNumArgs() < 3)
+    return State;
+
+  SourceLocation DomLoc = CE->getArg(0)->getExprLoc();
+  StringRef DomName = C.getMacroNameOrSpelling(DomLoc);
+  // White list the internal communication protocols.
+  if (DomName.equals("AF_SYSTEM") || DomName.equals("AF_LOCAL") ||
+      DomName.equals("AF_UNIX") || DomName.equals("AF_RESERVED_36"))
+    return State;
+  State = State->addTaint(CE, C.getLocationContext());
+  return State;
+}
+
+ProgramStateRef GenericTaintChecker::postScanf(const CallExpr *CE,
+                                                   CheckerContext &C) const {
+  ProgramStateRef State = C.getState();
+  if (CE->getNumArgs() < 2)
+    return State;
+
+  SVal x = State->getSVal(CE->getArg(1), C.getLocationContext());
+  // All arguments except for the very first one should get taint.
+  for (unsigned int i = 1; i < CE->getNumArgs(); ++i) {
+    // The arguments are pointer arguments. The data they are pointing at is
+    // tainted after the call.
+    const Expr* Arg = CE->getArg(i);
+        SymbolRef Sym = getPointedToSymbol(C, Arg);
+    if (Sym)
+      State = State->addTaint(Sym);
+  }
+  return State;
+}
+
+ProgramStateRef GenericTaintChecker::postRetTaint(const CallExpr *CE,
+                                                  CheckerContext &C) const {
+  return C.getState()->addTaint(CE, C.getLocationContext());
+}
+
+bool GenericTaintChecker::isStdin(const Expr *E, CheckerContext &C) {
+  ProgramStateRef State = C.getState();
+  SVal Val = State->getSVal(E, C.getLocationContext());
+
+  // stdin is a pointer, so it would be a region.
+  const MemRegion *MemReg = Val.getAsRegion();
+
+  // The region should be symbolic, we do not know it's value.
+  const SymbolicRegion *SymReg = dyn_cast_or_null<SymbolicRegion>(MemReg);
+  if (!SymReg)
+    return false;
+
+  // Get it's symbol and find the declaration region it's pointing to.
+  const SymbolRegionValue *Sm =dyn_cast<SymbolRegionValue>(SymReg->getSymbol());
+  if (!Sm)
+    return false;
+  const DeclRegion *DeclReg = dyn_cast_or_null<DeclRegion>(Sm->getRegion());
+  if (!DeclReg)
+    return false;
+
+  // This region corresponds to a declaration, find out if it's a global/extern
+  // variable named stdin with the proper type.
+  if (const VarDecl *D = dyn_cast_or_null<VarDecl>(DeclReg->getDecl())) {
+    D = D->getCanonicalDecl();
+    if ((D->getName().find("stdin") != StringRef::npos) && D->isExternC())
+        if (const PointerType * PtrTy =
+              dyn_cast<PointerType>(D->getType().getTypePtr()))
+          if (PtrTy->getPointeeType() == C.getASTContext().getFILEType())
+            return true;
+  }
+  return false;
+}
+
+static bool getPrintfFormatArgumentNum(const CallExpr *CE,
+                                       const CheckerContext &C,
+                                       unsigned int &ArgNum) {
+  // Find if the function contains a format string argument.
+  // Handles: fprintf, printf, sprintf, snprintf, vfprintf, vprintf, vsprintf,
+  // vsnprintf, syslog, custom annotated functions.
+  const FunctionDecl *FDecl = C.getCalleeDecl(CE);
+  if (!FDecl)
+    return false;
+  for (specific_attr_iterator<FormatAttr>
+         i = FDecl->specific_attr_begin<FormatAttr>(),
+         e = FDecl->specific_attr_end<FormatAttr>(); i != e ; ++i) {
+
+    const FormatAttr *Format = *i;
+    ArgNum = Format->getFormatIdx() - 1;
+    if ((Format->getType() == "printf") && CE->getNumArgs() > ArgNum)
+      return true;
+  }
+
+  // Or if a function is named setproctitle (this is a heuristic).
+  if (C.getCalleeName(CE).find("setproctitle") != StringRef::npos) {
+    ArgNum = 0;
+    return true;
+  }
+
+  return false;
+}
+
+bool GenericTaintChecker::generateReportIfTainted(const Expr *E,
+                                                  const char Msg[],
+                                                  CheckerContext &C) const {
+  assert(E);
+
+  // Check for taint.
+  ProgramStateRef State = C.getState();
+  if (!State->isTainted(getPointedToSymbol(C, E)) &&
+      !State->isTainted(E, C.getLocationContext()))
+    return false;
+
+  // Generate diagnostic.
+  if (ExplodedNode *N = C.addTransition()) {
+    initBugType();
+    BugReport *report = new BugReport(*BT, Msg, N);
+    report->addRange(E->getSourceRange());
+    C.EmitReport(report);
+    return true;
+  }
+  return false;
+}
+
+bool GenericTaintChecker::checkUncontrolledFormatString(const CallExpr *CE,
+                                                        CheckerContext &C) const{
+  // Check if the function contains a format string argument.
+  unsigned int ArgNum = 0;
+  if (!getPrintfFormatArgumentNum(CE, C, ArgNum))
+    return false;
+
+  // If either the format string content or the pointer itself are tainted, warn.
+  if (generateReportIfTainted(CE->getArg(ArgNum),
+                              MsgUncontrolledFormatString, C))
+    return true;
+  return false;
+}
+
+bool GenericTaintChecker::checkSystemCall(const CallExpr *CE,
+                                          StringRef Name,
+                                          CheckerContext &C) const {
+  // TODO: It might make sense to run this check on demand. In some cases, 
+  // we should check if the environment has been cleansed here. We also might 
+  // need to know if the user was reset before these calls(seteuid).
+  unsigned ArgNum = llvm::StringSwitch<unsigned>(Name)
+    .Case("system", 0)
+    .Case("popen", 0)
+    .Case("execl", 0)
+    .Case("execle", 0)
+    .Case("execlp", 0)
+    .Case("execv", 0)
+    .Case("execvp", 0)
+    .Case("execvP", 0)
+    .Case("execve", 0)
+    .Case("dlopen", 0)
+    .Default(UINT_MAX);
+
+  if (ArgNum == UINT_MAX || CE->getNumArgs() < (ArgNum + 1))
+    return false;
+
+  if (generateReportIfTainted(CE->getArg(ArgNum),
+                              MsgSanitizeSystemArgs, C))
+    return true;
+
+  return false;
+}
+
+// TODO: Should this check be a part of the CString checker?
+// If yes, should taint be a global setting?
+bool GenericTaintChecker::checkTaintedBufferSize(const CallExpr *CE,
+                                                 const FunctionDecl *FDecl,
+                                                 CheckerContext &C) const {
+  // If the function has a buffer size argument, set ArgNum.
+  unsigned ArgNum = InvalidArgIndex;
+  unsigned BId = 0;
+  if ( (BId = FDecl->getMemoryFunctionKind()) )
+    switch(BId) {
+    case Builtin::BImemcpy:
+    case Builtin::BImemmove:
+    case Builtin::BIstrncpy:
+      ArgNum = 2;
+      break;
+    case Builtin::BIstrndup:
+      ArgNum = 1;
+      break;
+    default:
+      break;
+    };
+
+  if (ArgNum == InvalidArgIndex) {
+    if (C.isCLibraryFunction(FDecl, "malloc") ||
+        C.isCLibraryFunction(FDecl, "calloc") ||
+        C.isCLibraryFunction(FDecl, "alloca"))
+      ArgNum = 0;
+    else if (C.isCLibraryFunction(FDecl, "memccpy"))
+      ArgNum = 3;
+    else if (C.isCLibraryFunction(FDecl, "realloc"))
+      ArgNum = 1;
+    else if (C.isCLibraryFunction(FDecl, "bcopy"))
+      ArgNum = 2;
+  }
+
+  if (ArgNum != InvalidArgIndex && CE->getNumArgs() > ArgNum &&
+      generateReportIfTainted(CE->getArg(ArgNum), MsgTaintedBufferSize, C))
+    return true;
+
+  return false;
+}
+
+void ento::registerGenericTaintChecker(CheckerManager &mgr) {
+  mgr.registerChecker<GenericTaintChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
new file mode 100644
index 0000000..c08f163
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
@@ -0,0 +1,747 @@
+//==- IdempotentOperationChecker.cpp - Idempotent Operations ----*- 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 set of path-sensitive checks for idempotent and/or
+// tautological operations. Each potential operation is checked along all paths
+// to see if every path results in a pointless operation.
+//                 +-------------------------------------------+
+//                 |Table of idempotent/tautological operations|
+//                 +-------------------------------------------+
+//+--------------------------------------------------------------------------+
+//|Operator | x op x | x op 1 | 1 op x | x op 0 | 0 op x | x op ~0 | ~0 op x |
+//+--------------------------------------------------------------------------+
+//  +, +=   |        |        |        |   x    |   x    |         |
+//  -, -=   |        |        |        |   x    |   -x   |         |
+//  *, *=   |        |   x    |   x    |   0    |   0    |         |
+//  /, /=   |   1    |   x    |        |  N/A   |   0    |         |
+//  &, &=   |   x    |        |        |   0    |   0    |   x     |    x
+//  |, |=   |   x    |        |        |   x    |   x    |   ~0    |    ~0
+//  ^, ^=   |   0    |        |        |   x    |   x    |         |
+//  <<, <<= |        |        |        |   x    |   0    |         |
+//  >>, >>= |        |        |        |   x    |   0    |         |
+//  ||      |   1    |   1    |   1    |   x    |   x    |   1     |    1
+//  &&      |   1    |   x    |   x    |   0    |   0    |   x     |    x
+//  =       |   x    |        |        |        |        |         |
+//  ==      |   1    |        |        |        |        |         |
+//  >=      |   1    |        |        |        |        |         |
+//  <=      |   1    |        |        |        |        |         |
+//  >       |   0    |        |        |        |        |         |
+//  <       |   0    |        |        |        |        |         |
+//  !=      |   0    |        |        |        |        |         |
+//===----------------------------------------------------------------------===//
+//
+// Things TODO:
+// - Improved error messages
+// - Handle mixed assumptions (which assumptions can belong together?)
+// - Finer grained false positive control (levels)
+// - Handling ~0 values
+
+#include "ClangSACheckers.h"
+#include "clang/Analysis/CFGStmtMap.h"
+#include "clang/Analysis/Analyses/PseudoConstantAnalysis.h"
+#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/AST/Stmt.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class IdempotentOperationChecker
+  : public Checker<check::PreStmt<BinaryOperator>,
+                     check::PostStmt<BinaryOperator>,
+                     check::EndAnalysis> {
+public:
+  void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
+  void checkPostStmt(const BinaryOperator *B, CheckerContext &C) const;
+  void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const;
+
+private:
+  // Our assumption about a particular operation.
+  enum Assumption { Possible = 0, Impossible, Equal, LHSis1, RHSis1, LHSis0,
+      RHSis0 };
+
+  static void UpdateAssumption(Assumption &A, const Assumption &New);
+
+  // False positive reduction methods
+  static bool isSelfAssign(const Expr *LHS, const Expr *RHS);
+  static bool isUnused(const Expr *E, AnalysisDeclContext *AC);
+  static bool isTruncationExtensionAssignment(const Expr *LHS,
+                                              const Expr *RHS);
+  static bool pathWasCompletelyAnalyzed(AnalysisDeclContext *AC,
+                                        const CFGBlock *CB,
+                                        const CoreEngine &CE);
+  static bool CanVary(const Expr *Ex,
+                      AnalysisDeclContext *AC);
+  static bool isConstantOrPseudoConstant(const DeclRefExpr *DR,
+                                         AnalysisDeclContext *AC);
+  static bool containsNonLocalVarDecl(const Stmt *S);
+
+  // Hash table and related data structures
+  struct BinaryOperatorData {
+    BinaryOperatorData() : assumption(Possible) {}
+
+    Assumption assumption;
+    ExplodedNodeSet explodedNodes; // Set of ExplodedNodes that refer to a
+                                   // BinaryOperator
+  };
+  typedef llvm::DenseMap<const BinaryOperator *, BinaryOperatorData>
+      AssumptionMap;
+  mutable AssumptionMap hash;
+};
+}
+
+void IdempotentOperationChecker::checkPreStmt(const BinaryOperator *B,
+                                              CheckerContext &C) const {
+  // Find or create an entry in the hash for this BinaryOperator instance.
+  // If we haven't done a lookup before, it will get default initialized to
+  // 'Possible'. At this stage we do not store the ExplodedNode, as it has not
+  // been created yet.
+  BinaryOperatorData &Data = hash[B];
+  Assumption &A = Data.assumption;
+  AnalysisDeclContext *AC = C.getCurrentAnalysisDeclContext();
+
+  // If we already have visited this node on a path that does not contain an
+  // idempotent operation, return immediately.
+  if (A == Impossible)
+    return;
+
+  // Retrieve both sides of the operator and determine if they can vary (which
+  // may mean this is a false positive.
+  const Expr *LHS = B->getLHS();
+  const Expr *RHS = B->getRHS();
+
+  // At this stage we can calculate whether each side contains a false positive
+  // that applies to all operators. We only need to calculate this the first
+  // time.
+  bool LHSContainsFalsePositive = false, RHSContainsFalsePositive = false;
+  if (A == Possible) {
+    // An expression contains a false positive if it can't vary, or if it
+    // contains a known false positive VarDecl.
+    LHSContainsFalsePositive = !CanVary(LHS, AC)
+        || containsNonLocalVarDecl(LHS);
+    RHSContainsFalsePositive = !CanVary(RHS, AC)
+        || containsNonLocalVarDecl(RHS);
+  }
+
+  ProgramStateRef state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal LHSVal = state->getSVal(LHS, LCtx);
+  SVal RHSVal = state->getSVal(RHS, LCtx);
+
+  // If either value is unknown, we can't be 100% sure of all paths.
+  if (LHSVal.isUnknownOrUndef() || RHSVal.isUnknownOrUndef()) {
+    A = Impossible;
+    return;
+  }
+  BinaryOperator::Opcode Op = B->getOpcode();
+
+  // Dereference the LHS SVal if this is an assign operation
+  switch (Op) {
+  default:
+    break;
+
+  // Fall through intentional
+  case BO_AddAssign:
+  case BO_SubAssign:
+  case BO_MulAssign:
+  case BO_DivAssign:
+  case BO_AndAssign:
+  case BO_OrAssign:
+  case BO_XorAssign:
+  case BO_ShlAssign:
+  case BO_ShrAssign:
+  case BO_Assign:
+  // Assign statements have one extra level of indirection
+    if (!isa<Loc>(LHSVal)) {
+      A = Impossible;
+      return;
+    }
+    LHSVal = state->getSVal(cast<Loc>(LHSVal), LHS->getType());
+  }
+
+
+  // We now check for various cases which result in an idempotent operation.
+
+  // x op x
+  switch (Op) {
+  default:
+    break; // We don't care about any other operators.
+
+  // Fall through intentional
+  case BO_Assign:
+    // x Assign x can be used to silence unused variable warnings intentionally.
+    // If this is a self assignment and the variable is referenced elsewhere,
+    // and the assignment is not a truncation or extension, then it is a false
+    // positive.
+    if (isSelfAssign(LHS, RHS)) {
+      if (!isUnused(LHS, AC) && !isTruncationExtensionAssignment(LHS, RHS)) {
+        UpdateAssumption(A, Equal);
+        return;
+      }
+      else {
+        A = Impossible;
+        return;
+      }
+    }
+
+  case BO_SubAssign:
+  case BO_DivAssign:
+  case BO_AndAssign:
+  case BO_OrAssign:
+  case BO_XorAssign:
+  case BO_Sub:
+  case BO_Div:
+  case BO_And:
+  case BO_Or:
+  case BO_Xor:
+  case BO_LOr:
+  case BO_LAnd:
+  case BO_EQ:
+  case BO_NE:
+    if (LHSVal != RHSVal || LHSContainsFalsePositive
+        || RHSContainsFalsePositive)
+      break;
+    UpdateAssumption(A, Equal);
+    return;
+  }
+
+  // x op 1
+  switch (Op) {
+   default:
+     break; // We don't care about any other operators.
+
+   // Fall through intentional
+   case BO_MulAssign:
+   case BO_DivAssign:
+   case BO_Mul:
+   case BO_Div:
+   case BO_LOr:
+   case BO_LAnd:
+     if (!RHSVal.isConstant(1) || RHSContainsFalsePositive)
+       break;
+     UpdateAssumption(A, RHSis1);
+     return;
+  }
+
+  // 1 op x
+  switch (Op) {
+  default:
+    break; // We don't care about any other operators.
+
+  // Fall through intentional
+  case BO_MulAssign:
+  case BO_Mul:
+  case BO_LOr:
+  case BO_LAnd:
+    if (!LHSVal.isConstant(1) || LHSContainsFalsePositive)
+      break;
+    UpdateAssumption(A, LHSis1);
+    return;
+  }
+
+  // x op 0
+  switch (Op) {
+  default:
+    break; // We don't care about any other operators.
+
+  // Fall through intentional
+  case BO_AddAssign:
+  case BO_SubAssign:
+  case BO_MulAssign:
+  case BO_AndAssign:
+  case BO_OrAssign:
+  case BO_XorAssign:
+  case BO_Add:
+  case BO_Sub:
+  case BO_Mul:
+  case BO_And:
+  case BO_Or:
+  case BO_Xor:
+  case BO_Shl:
+  case BO_Shr:
+  case BO_LOr:
+  case BO_LAnd:
+    if (!RHSVal.isConstant(0) || RHSContainsFalsePositive)
+      break;
+    UpdateAssumption(A, RHSis0);
+    return;
+  }
+
+  // 0 op x
+  switch (Op) {
+  default:
+    break; // We don't care about any other operators.
+
+  // Fall through intentional
+  //case BO_AddAssign: // Common false positive
+  case BO_SubAssign: // Check only if unsigned
+  case BO_MulAssign:
+  case BO_DivAssign:
+  case BO_AndAssign:
+  //case BO_OrAssign: // Common false positive
+  //case BO_XorAssign: // Common false positive
+  case BO_ShlAssign:
+  case BO_ShrAssign:
+  case BO_Add:
+  case BO_Sub:
+  case BO_Mul:
+  case BO_Div:
+  case BO_And:
+  case BO_Or:
+  case BO_Xor:
+  case BO_Shl:
+  case BO_Shr:
+  case BO_LOr:
+  case BO_LAnd:
+    if (!LHSVal.isConstant(0) || LHSContainsFalsePositive)
+      break;
+    UpdateAssumption(A, LHSis0);
+    return;
+  }
+
+  // If we get to this point, there has been a valid use of this operation.
+  A = Impossible;
+}
+
+// At the post visit stage, the predecessor ExplodedNode will be the
+// BinaryOperator that was just created. We use this hook to collect the
+// ExplodedNode.
+void IdempotentOperationChecker::checkPostStmt(const BinaryOperator *B,
+                                               CheckerContext &C) const {
+  // Add the ExplodedNode we just visited
+  BinaryOperatorData &Data = hash[B];
+
+  const Stmt *predStmt 
+    = cast<StmtPoint>(C.getPredecessor()->getLocation()).getStmt();
+  
+  // Ignore implicit calls to setters.
+  if (!isa<BinaryOperator>(predStmt))
+    return;
+
+  Data.explodedNodes.Add(C.getPredecessor());
+}
+
+void IdempotentOperationChecker::checkEndAnalysis(ExplodedGraph &G,
+                                                  BugReporter &BR,
+                                                  ExprEngine &Eng) const {
+  BugType *BT = new BugType("Idempotent operation", "Dead code");
+  // Iterate over the hash to see if we have any paths with definite
+  // idempotent operations.
+  for (AssumptionMap::const_iterator i = hash.begin(); i != hash.end(); ++i) {
+    // Unpack the hash contents
+    const BinaryOperatorData &Data = i->second;
+    const Assumption &A = Data.assumption;
+    const ExplodedNodeSet &ES = Data.explodedNodes;
+
+    // If there are no nodes accosted with the expression, nothing to report.
+    // FIXME: This is possible because the checker does part of processing in
+    // checkPreStmt and part in checkPostStmt.
+    if (ES.begin() == ES.end())
+      continue;
+
+    const BinaryOperator *B = i->first;
+
+    if (A == Impossible)
+      continue;
+
+    // If the analyzer did not finish, check to see if we can still emit this
+    // warning
+    if (Eng.hasWorkRemaining()) {
+      // If we can trace back
+      AnalysisDeclContext *AC = (*ES.begin())->getLocationContext()
+                                         ->getAnalysisDeclContext();
+      if (!pathWasCompletelyAnalyzed(AC,
+                                     AC->getCFGStmtMap()->getBlock(B),
+                                     Eng.getCoreEngine()))
+        continue;
+    }
+
+    // Select the error message and SourceRanges to report.
+    SmallString<128> buf;
+    llvm::raw_svector_ostream os(buf);
+    bool LHSRelevant = false, RHSRelevant = false;
+    switch (A) {
+    case Equal:
+      LHSRelevant = true;
+      RHSRelevant = true;
+      if (B->getOpcode() == BO_Assign)
+        os << "Assigned value is always the same as the existing value";
+      else
+        os << "Both operands to '" << B->getOpcodeStr()
+           << "' always have the same value";
+      break;
+    case LHSis1:
+      LHSRelevant = true;
+      os << "The left operand to '" << B->getOpcodeStr() << "' is always 1";
+      break;
+    case RHSis1:
+      RHSRelevant = true;
+      os << "The right operand to '" << B->getOpcodeStr() << "' is always 1";
+      break;
+    case LHSis0:
+      LHSRelevant = true;
+      os << "The left operand to '" << B->getOpcodeStr() << "' is always 0";
+      break;
+    case RHSis0:
+      RHSRelevant = true;
+      os << "The right operand to '" << B->getOpcodeStr() << "' is always 0";
+      break;
+    case Possible:
+      llvm_unreachable("Operation was never marked with an assumption");
+    case Impossible:
+      llvm_unreachable(0);
+    }
+
+    // Add a report for each ExplodedNode
+    for (ExplodedNodeSet::iterator I = ES.begin(), E = ES.end(); I != E; ++I) {
+      BugReport *report = new BugReport(*BT, os.str(), *I);
+
+      // Add source ranges and visitor hooks
+      if (LHSRelevant) {
+        const Expr *LHS = i->first->getLHS();
+        report->addRange(LHS->getSourceRange());
+        FindLastStoreBRVisitor::registerStatementVarDecls(*report, LHS);
+      }
+      if (RHSRelevant) {
+        const Expr *RHS = i->first->getRHS();
+        report->addRange(i->first->getRHS()->getSourceRange());
+        FindLastStoreBRVisitor::registerStatementVarDecls(*report, RHS);
+      }
+
+      BR.EmitReport(report);
+    }
+  }
+
+  hash.clear();
+}
+
+// Updates the current assumption given the new assumption
+inline void IdempotentOperationChecker::UpdateAssumption(Assumption &A,
+                                                        const Assumption &New) {
+// If the assumption is the same, there is nothing to do
+  if (A == New)
+    return;
+
+  switch (A) {
+  // If we don't currently have an assumption, set it
+  case Possible:
+    A = New;
+    return;
+
+  // If we have determined that a valid state happened, ignore the new
+  // assumption.
+  case Impossible:
+    return;
+
+  // Any other case means that we had a different assumption last time. We don't
+  // currently support mixing assumptions for diagnostic reasons, so we set
+  // our assumption to be impossible.
+  default:
+    A = Impossible;
+    return;
+  }
+}
+
+// Check for a statement where a variable is self assigned to possibly avoid an
+// unused variable warning.
+bool IdempotentOperationChecker::isSelfAssign(const Expr *LHS, const Expr *RHS) {
+  LHS = LHS->IgnoreParenCasts();
+  RHS = RHS->IgnoreParenCasts();
+
+  const DeclRefExpr *LHS_DR = dyn_cast<DeclRefExpr>(LHS);
+  if (!LHS_DR)
+    return false;
+
+  const VarDecl *VD = dyn_cast<VarDecl>(LHS_DR->getDecl());
+  if (!VD)
+    return false;
+
+  const DeclRefExpr *RHS_DR = dyn_cast<DeclRefExpr>(RHS);
+  if (!RHS_DR)
+    return false;
+
+  if (VD != RHS_DR->getDecl())
+    return false;
+
+  return true;
+}
+
+// Returns true if the Expr points to a VarDecl that is not read anywhere
+// outside of self-assignments.
+bool IdempotentOperationChecker::isUnused(const Expr *E,
+                                          AnalysisDeclContext *AC) {
+  if (!E)
+    return false;
+
+  const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts());
+  if (!DR)
+    return false;
+
+  const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
+  if (!VD)
+    return false;
+
+  if (AC->getPseudoConstantAnalysis()->wasReferenced(VD))
+    return false;
+
+  return true;
+}
+
+// Check for self casts truncating/extending a variable
+bool IdempotentOperationChecker::isTruncationExtensionAssignment(
+                                                              const Expr *LHS,
+                                                              const Expr *RHS) {
+
+  const DeclRefExpr *LHS_DR = dyn_cast<DeclRefExpr>(LHS->IgnoreParenCasts());
+  if (!LHS_DR)
+    return false;
+
+  const VarDecl *VD = dyn_cast<VarDecl>(LHS_DR->getDecl());
+  if (!VD)
+    return false;
+
+  const DeclRefExpr *RHS_DR = dyn_cast<DeclRefExpr>(RHS->IgnoreParenCasts());
+  if (!RHS_DR)
+    return false;
+
+  if (VD != RHS_DR->getDecl())
+     return false;
+
+  return dyn_cast<DeclRefExpr>(RHS->IgnoreParenLValueCasts()) == NULL;
+}
+
+// Returns false if a path to this block was not completely analyzed, or true
+// otherwise.
+bool
+IdempotentOperationChecker::pathWasCompletelyAnalyzed(AnalysisDeclContext *AC,
+                                                      const CFGBlock *CB,
+                                                      const CoreEngine &CE) {
+
+  CFGReverseBlockReachabilityAnalysis *CRA = AC->getCFGReachablityAnalysis();
+  
+  // Test for reachability from any aborted blocks to this block
+  typedef CoreEngine::BlocksExhausted::const_iterator ExhaustedIterator;
+  for (ExhaustedIterator I = CE.blocks_exhausted_begin(),
+      E = CE.blocks_exhausted_end(); I != E; ++I) {
+    const BlockEdge &BE =  I->first;
+
+    // The destination block on the BlockEdge is the first block that was not
+    // analyzed. If we can reach this block from the aborted block, then this
+    // block was not completely analyzed.
+    //
+    // Also explicitly check if the current block is the destination block.
+    // While technically reachable, it means we aborted the analysis on
+    // a path that included that block.
+    const CFGBlock *destBlock = BE.getDst();
+    if (destBlock == CB || CRA->isReachable(destBlock, CB))
+      return false;
+  }
+
+  // Test for reachability from blocks we just gave up on.
+  typedef CoreEngine::BlocksAborted::const_iterator AbortedIterator;
+  for (AbortedIterator I = CE.blocks_aborted_begin(),
+       E = CE.blocks_aborted_end(); I != E; ++I) {
+    const CFGBlock *destBlock = I->first;
+    if (destBlock == CB || CRA->isReachable(destBlock, CB))
+      return false;
+  }
+  
+  // For the items still on the worklist, see if they are in blocks that
+  // can eventually reach 'CB'.
+  class VisitWL : public WorkList::Visitor {
+    const CFGStmtMap *CBM;
+    const CFGBlock *TargetBlock;
+    CFGReverseBlockReachabilityAnalysis &CRA;
+  public:
+    VisitWL(const CFGStmtMap *cbm, const CFGBlock *targetBlock,
+            CFGReverseBlockReachabilityAnalysis &cra)
+      : CBM(cbm), TargetBlock(targetBlock), CRA(cra) {}
+    virtual bool visit(const WorkListUnit &U) {
+      ProgramPoint P = U.getNode()->getLocation();
+      const CFGBlock *B = 0;
+      if (StmtPoint *SP = dyn_cast<StmtPoint>(&P)) {
+        B = CBM->getBlock(SP->getStmt());
+      }
+      else if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
+        B = BE->getDst();
+      }
+      else if (BlockEntrance *BEnt = dyn_cast<BlockEntrance>(&P)) {
+        B = BEnt->getBlock();
+      }
+      else if (BlockExit *BExit = dyn_cast<BlockExit>(&P)) {
+        B = BExit->getBlock();
+      }
+      if (!B)
+        return true;
+      
+      return B == TargetBlock || CRA.isReachable(B, TargetBlock);
+    }
+  };
+  VisitWL visitWL(AC->getCFGStmtMap(), CB, *CRA);
+  // Were there any items in the worklist that could potentially reach
+  // this block?
+  if (CE.getWorkList()->visitItemsInWorkList(visitWL))
+    return false;
+
+  // Verify that this block is reachable from the entry block
+  if (!CRA->isReachable(&AC->getCFG()->getEntry(), CB))
+    return false;
+
+  // If we get to this point, there is no connection to the entry block or an
+  // aborted block. This path is unreachable and we can report the error.
+  return true;
+}
+
+// Recursive function that determines whether an expression contains any element
+// that varies. This could be due to a compile-time constant like sizeof. An
+// expression may also involve a variable that behaves like a constant. The
+// function returns true if the expression varies, and false otherwise.
+bool IdempotentOperationChecker::CanVary(const Expr *Ex,
+                                         AnalysisDeclContext *AC) {
+  // Parentheses and casts are irrelevant here
+  Ex = Ex->IgnoreParenCasts();
+
+  if (Ex->getLocStart().isMacroID())
+    return false;
+
+  switch (Ex->getStmtClass()) {
+  // Trivially true cases
+  case Stmt::ArraySubscriptExprClass:
+  case Stmt::MemberExprClass:
+  case Stmt::StmtExprClass:
+  case Stmt::CallExprClass:
+  case Stmt::VAArgExprClass:
+  case Stmt::ShuffleVectorExprClass:
+    return true;
+  default:
+    return true;
+
+  // Trivially false cases
+  case Stmt::IntegerLiteralClass:
+  case Stmt::CharacterLiteralClass:
+  case Stmt::FloatingLiteralClass:
+  case Stmt::PredefinedExprClass:
+  case Stmt::ImaginaryLiteralClass:
+  case Stmt::StringLiteralClass:
+  case Stmt::OffsetOfExprClass:
+  case Stmt::CompoundLiteralExprClass:
+  case Stmt::AddrLabelExprClass:
+  case Stmt::BinaryTypeTraitExprClass:
+  case Stmt::GNUNullExprClass:
+  case Stmt::InitListExprClass:
+  case Stmt::DesignatedInitExprClass:
+  case Stmt::BlockExprClass:
+    return false;
+
+  // Cases requiring custom logic
+  case Stmt::UnaryExprOrTypeTraitExprClass: {
+    const UnaryExprOrTypeTraitExpr *SE = 
+                       cast<const UnaryExprOrTypeTraitExpr>(Ex);
+    if (SE->getKind() != UETT_SizeOf)
+      return false;
+    return SE->getTypeOfArgument()->isVariableArrayType();
+  }
+  case Stmt::DeclRefExprClass:
+    // Check for constants/pseudoconstants
+    return !isConstantOrPseudoConstant(cast<DeclRefExpr>(Ex), AC);
+
+  // The next cases require recursion for subexpressions
+  case Stmt::BinaryOperatorClass: {
+    const BinaryOperator *B = cast<const BinaryOperator>(Ex);
+
+    // Exclude cases involving pointer arithmetic.  These are usually
+    // false positives.
+    if (B->getOpcode() == BO_Sub || B->getOpcode() == BO_Add)
+      if (B->getLHS()->getType()->getAs<PointerType>())
+        return false;
+
+    return CanVary(B->getRHS(), AC)
+        || CanVary(B->getLHS(), AC);
+   }
+  case Stmt::UnaryOperatorClass: {
+    const UnaryOperator *U = cast<const UnaryOperator>(Ex);
+    // Handle trivial case first
+    switch (U->getOpcode()) {
+    case UO_Extension:
+      return false;
+    default:
+      return CanVary(U->getSubExpr(), AC);
+    }
+  }
+  case Stmt::ChooseExprClass:
+    return CanVary(cast<const ChooseExpr>(Ex)->getChosenSubExpr(
+        AC->getASTContext()), AC);
+  case Stmt::ConditionalOperatorClass:
+  case Stmt::BinaryConditionalOperatorClass:
+    return CanVary(cast<AbstractConditionalOperator>(Ex)->getCond(), AC);
+  }
+}
+
+// Returns true if a DeclRefExpr is or behaves like a constant.
+bool IdempotentOperationChecker::isConstantOrPseudoConstant(
+                                                          const DeclRefExpr *DR,
+                                                          AnalysisDeclContext *AC) {
+  // Check if the type of the Decl is const-qualified
+  if (DR->getType().isConstQualified())
+    return true;
+
+  // Check for an enum
+  if (isa<EnumConstantDecl>(DR->getDecl()))
+    return true;
+
+  const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
+  if (!VD)
+    return true;
+
+  // Check if the Decl behaves like a constant. This check also takes care of
+  // static variables, which can only change between function calls if they are
+  // modified in the AST.
+  PseudoConstantAnalysis *PCA = AC->getPseudoConstantAnalysis();
+  if (PCA->isPseudoConstant(VD))
+    return true;
+
+  return false;
+}
+
+// Recursively find any substatements containing VarDecl's with storage other
+// than local
+bool IdempotentOperationChecker::containsNonLocalVarDecl(const Stmt *S) {
+  const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S);
+
+  if (DR)
+    if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
+      if (!VD->hasLocalStorage())
+        return true;
+
+  for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
+      ++I)
+    if (const Stmt *child = *I)
+      if (containsNonLocalVarDecl(child))
+        return true;
+
+  return false;
+}
+
+
+void ento::registerIdempotentOperationChecker(CheckerManager &mgr) {
+  mgr.registerChecker<IdempotentOperationChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h b/clang/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h
new file mode 100644
index 0000000..e35557f
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h
@@ -0,0 +1,22 @@
+//==--- InterCheckerAPI.h ---------------------------------------*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This file allows introduction of checker dependencies. It contains APIs for
+// inter-checker communications.
+//===----------------------------------------------------------------------===//
+
+#ifndef INTERCHECKERAPI_H_
+#define INTERCHECKERAPI_H_
+namespace clang {
+namespace ento {
+
+/// Register the checker which evaluates CString API calls.
+void registerCStringCheckerBasic(CheckerManager &Mgr);
+
+}}
+#endif /* INTERCHECKERAPI_H_ */
diff --git a/clang/lib/StaticAnalyzer/Checkers/IntervalTest.cpp b/clang/lib/StaticAnalyzer/Checkers/IntervalTest.cpp
new file mode 100644
index 0000000..2f3e155
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/IntervalTest.cpp
@@ -0,0 +1,25 @@
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "clang/Analysis/Analyses/Interval.h"
+#include "clang/Analysis/CallGraph.h"
+#include "llvm/Support/Process.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class IntervalTest: public Checker<check::ASTCodeBody> {
+public:
+  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
+                        BugReporter &BR) const {
+    if (IntervalAnalysis *a = mgr.getAnalysis<IntervalAnalysis>(D)) {
+      a->runOnAllBlocks();
+    }
+  }
+};
+}
+
+void ento::registerIntervalTestChecker(CheckerManager &mgr) {
+  mgr.registerChecker<IntervalTest>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp
new file mode 100644
index 0000000..b0bac33
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp
@@ -0,0 +1,603 @@
+//=== IteratorsChecker.cpp - Check for Invalidated Iterators ------*- C++ -*----
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines IteratorsChecker, a number of small checks for conditions
+// leading to invalid iterators being used.
+// FIXME: Currently only supports 'vector' and 'deque'
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/DeclTemplate.h"
+#include "clang/Basic/SourceManager.h"
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/StringSwitch.h"
+
+
+using namespace clang;
+using namespace ento;
+
+// This is the state associated with each iterator which includes both the
+// kind of state and the instance used to initialize it.
+// FIXME: add location where invalidated for better error reporting.
+namespace {
+class RefState {
+  enum Kind { BeginValid, EndValid, Invalid, Undefined, Unknown } K;
+  const void *VR;
+
+public:
+  RefState(Kind k, const void *vr) : K(k), VR(vr) {}
+
+  bool isValid() const { return K == BeginValid || K == EndValid; }
+  bool isInvalid() const { return K == Invalid; }
+  bool isUndefined() const { return K == Undefined; }
+  bool isUnknown() const { return K == Unknown; }
+  const MemRegion *getMemRegion() const {
+    if (K == BeginValid || K == EndValid)
+      return(const MemRegion *)VR;
+    return 0;
+  }
+  const MemberExpr *getMemberExpr() const {
+    if (K == Invalid)
+      return(const MemberExpr *)VR;
+    return 0;
+  }
+
+  bool operator==(const RefState &X) const {
+    return K == X.K && VR == X.VR;
+  }
+
+  static RefState getBeginValid(const MemRegion *vr) {
+    assert(vr);
+    return RefState(BeginValid, vr);
+  }
+  static RefState getEndValid(const MemRegion *vr) {
+    assert(vr);
+    return RefState(EndValid, vr);
+  }
+  static RefState getInvalid( const MemberExpr *ME ) {
+    return RefState(Invalid, ME);
+  }
+  static RefState getUndefined( void ) {
+    return RefState(Undefined, 0);
+  }
+  static RefState getUnknown( void ) {
+    return RefState(Unknown, 0);
+  }
+
+  void Profile(llvm::FoldingSetNodeID &ID) const {
+    ID.AddInteger(K);
+    ID.AddPointer(VR);
+  }
+};
+
+enum RefKind { NoKind, VectorKind, VectorIteratorKind };
+
+class IteratorsChecker : 
+    public Checker<check::PreStmt<CXXOperatorCallExpr>,
+                   check::PreStmt<DeclStmt>,
+                   check::PreStmt<CXXMemberCallExpr>,
+                   check::PreStmt<CallExpr> >
+  {
+  // Used when parsing iterators and vectors and deques.
+  BuiltinBug *BT_Invalid, *BT_Undefined, *BT_Incompatible;
+
+public:
+  IteratorsChecker() :
+    BT_Invalid(0), BT_Undefined(0), BT_Incompatible(0)
+  {}
+  static void *getTag() { static int tag; return &tag; }
+    
+  // Checker entry points.
+  void checkPreStmt(const CXXOperatorCallExpr *OCE,
+                    CheckerContext &C) const;
+
+  void checkPreStmt(const DeclStmt *DS,
+                    CheckerContext &C) const;
+
+  void checkPreStmt(const CXXMemberCallExpr *MCE,
+                    CheckerContext &C) const;
+
+  void checkPreStmt(const CallExpr *CE,
+                    CheckerContext &C) const;
+
+private:
+  ProgramStateRef handleAssign(ProgramStateRef state,
+                                   const Expr *lexp,
+                                   const Expr *rexp,
+                                   const LocationContext *LC) const;
+
+  ProgramStateRef handleAssign(ProgramStateRef state,
+                                   const MemRegion *MR,
+                                   const Expr *rexp,
+                                   const LocationContext *LC) const;
+
+  ProgramStateRef invalidateIterators(ProgramStateRef state,
+                                          const MemRegion *MR,
+                                          const MemberExpr *ME) const;
+
+  void checkExpr(CheckerContext &C, const Expr *E) const;
+
+  void checkArgs(CheckerContext &C, const CallExpr *CE) const;
+
+  const MemRegion *getRegion(ProgramStateRef state,
+                             const Expr *E,
+                             const LocationContext *LC) const;
+
+  const DeclRefExpr *getDeclRefExpr(const Expr *E) const;
+};
+
+class IteratorState {
+public:
+  typedef llvm::ImmutableMap<const MemRegion *, RefState> EntryMap;
+};
+} //end anonymous namespace
+
+namespace clang {
+  namespace ento {
+    template <>
+    struct ProgramStateTrait<IteratorState> 
+      : public ProgramStatePartialTrait<IteratorState::EntryMap> {
+      static void *GDMIndex() { return IteratorsChecker::getTag(); }
+    };
+  }
+}
+
+void ento::registerIteratorsChecker(CheckerManager &mgr) {
+  mgr.registerChecker<IteratorsChecker>();
+}
+
+// ===============================================
+// Utility functions used by visitor functions
+// ===============================================
+
+// check a templated type for std::vector or std::deque
+static RefKind getTemplateKind(const NamedDecl *td) {
+  const DeclContext *dc = td->getDeclContext();
+  const NamespaceDecl *nameSpace = dyn_cast<NamespaceDecl>(dc);
+  if (!nameSpace || !isa<TranslationUnitDecl>(nameSpace->getDeclContext())
+      || nameSpace->getName() != "std")
+    return NoKind;
+  
+  StringRef name = td->getName();
+  return llvm::StringSwitch<RefKind>(name)
+    .Cases("vector", "deque", VectorKind)
+    .Default(NoKind);
+}
+
+static RefKind getTemplateKind(const DeclContext *dc) {
+  if (const ClassTemplateSpecializationDecl *td =
+      dyn_cast<ClassTemplateSpecializationDecl>(dc))
+    return getTemplateKind(cast<NamedDecl>(td));
+  return NoKind;
+}
+
+static RefKind getTemplateKind(const TypedefType *tdt) {
+  const TypedefNameDecl *td = tdt->getDecl();
+  RefKind parentKind = getTemplateKind(td->getDeclContext());
+  if (parentKind == VectorKind) {
+    return llvm::StringSwitch<RefKind>(td->getName())
+    .Cases("iterator",
+           "const_iterator",
+           "reverse_iterator", VectorIteratorKind)
+    .Default(NoKind);
+  }
+  return NoKind;
+}
+
+static RefKind getTemplateKind(const TemplateSpecializationType *tsp) {
+  const TemplateName &tname = tsp->getTemplateName();
+  TemplateDecl *td = tname.getAsTemplateDecl();
+  if (!td)
+    return NoKind;
+  return getTemplateKind(td);
+}
+
+static RefKind getTemplateKind(QualType T) {
+  if (const TemplateSpecializationType *tsp = 
+      T->getAs<TemplateSpecializationType>()) {
+    return getTemplateKind(tsp);      
+  }
+  if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) {
+    QualType namedType = ET->getNamedType();
+    if (const TypedefType *tdt = namedType->getAs<TypedefType>()) 
+      return getTemplateKind(tdt);
+    if (const TemplateSpecializationType *tsp = 
+        namedType->getAs<TemplateSpecializationType>()) {
+      return getTemplateKind(tsp);      
+    }
+  }
+  return NoKind;  
+}
+
+// Iterate through our map and invalidate any iterators that were
+// initialized fromt the specified instance MemRegion.
+ProgramStateRef IteratorsChecker::invalidateIterators(ProgramStateRef state,
+                          const MemRegion *MR, const MemberExpr *ME) const {
+  IteratorState::EntryMap Map = state->get<IteratorState>();
+  if (Map.isEmpty())
+    return state;
+
+  // Loop over the entries in the current state.
+  // The key doesn't change, so the map iterators won't change.
+  for (IteratorState::EntryMap::iterator I = Map.begin(), E = Map.end();
+                                                            I != E; ++I) {
+    RefState RS = I.getData();
+    if (RS.getMemRegion() == MR)
+      state = state->set<IteratorState>(I.getKey(), RefState::getInvalid(ME));
+  }
+
+  return state;
+}
+
+// Handle assigning to an iterator where we don't have the LValue MemRegion.
+ProgramStateRef IteratorsChecker::handleAssign(ProgramStateRef state,
+    const Expr *lexp, const Expr *rexp, const LocationContext *LC) const {
+  // Skip the cast if present.
+  if (const MaterializeTemporaryExpr *M 
+                                    = dyn_cast<MaterializeTemporaryExpr>(lexp))
+    lexp = M->GetTemporaryExpr();
+  if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(lexp))
+    lexp = ICE->getSubExpr();
+  SVal sv = state->getSVal(lexp, LC);
+  const MemRegion *MR = sv.getAsRegion();
+  if (!MR)
+    return state;
+  RefKind kind = getTemplateKind(lexp->getType());
+
+  // If assigning to a vector, invalidate any iterators currently associated.
+  if (kind == VectorKind)
+    return invalidateIterators(state, MR, 0);
+
+  // Make sure that we are assigning to an iterator.
+  if (getTemplateKind(lexp->getType()) != VectorIteratorKind)
+    return state;
+  return handleAssign(state, MR, rexp, LC);
+}
+
+// handle assigning to an iterator
+ProgramStateRef IteratorsChecker::handleAssign(ProgramStateRef state,
+    const MemRegion *MR, const Expr *rexp, const LocationContext *LC) const {
+  // Assume unknown until we find something definite.
+  state = state->set<IteratorState>(MR, RefState::getUnknown());
+  if (const MaterializeTemporaryExpr *M 
+                                    = dyn_cast<MaterializeTemporaryExpr>(rexp))
+    rexp = M->GetTemporaryExpr();
+  if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(rexp))
+    rexp = ICE->getSubExpr();
+  // Need to handle three cases: MemberCall, copy, copy with addition.
+  if (const CallExpr *CE = dyn_cast<CallExpr>(rexp)) {
+    // Handle MemberCall.
+    if (const MemberExpr *ME = dyn_cast<MemberExpr>(CE->getCallee())) {
+      const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ME->getBase());
+      if (!DRE)
+        return state;
+      // Verify that the type is std::vector<T>.
+      if (getTemplateKind(DRE->getType()) != VectorKind)
+          return state;
+      // Now get the MemRegion associated with the instance.
+      const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl());
+      if (!VD)
+        return state;
+      const MemRegion *IMR = state->getRegion(VD, LC);
+      if (!IMR)
+        return state;
+      // Finally, see if it is one of the calls that will create
+      // a valid iterator and mark it if so, else mark as Unknown.
+      StringRef mName = ME->getMemberDecl()->getName();
+      
+      if (llvm::StringSwitch<bool>(mName)        
+          .Cases("begin", "insert", "erase", true).Default(false)) {
+        return state->set<IteratorState>(MR, RefState::getBeginValid(IMR));
+      }
+      if (mName == "end")
+        return state->set<IteratorState>(MR, RefState::getEndValid(IMR));
+
+      return state->set<IteratorState>(MR, RefState::getUnknown());
+    }
+  }
+  // Handle straight copy from another iterator.
+  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(rexp)) {
+    if (getTemplateKind(DRE->getType()) != VectorIteratorKind)
+      return state;
+    // Now get the MemRegion associated with the instance.
+    const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl());
+    if (!VD)
+      return state;
+    const MemRegion *IMR = state->getRegion(VD, LC);
+    if (!IMR)
+      return state;
+    // Get the RefState of the iterator being copied.
+    const RefState *RS = state->get<IteratorState>(IMR);
+    if (!RS)
+      return state;
+    // Use it to set the state of the LValue.
+    return state->set<IteratorState>(MR, *RS);
+  }
+  // If we have operator+ or operator- ...
+  if (const CXXOperatorCallExpr *OCE = dyn_cast<CXXOperatorCallExpr>(rexp)) {
+    OverloadedOperatorKind Kind = OCE->getOperator();
+    if (Kind == OO_Plus || Kind == OO_Minus) {
+      // Check left side of tree for a valid value.
+      state = handleAssign( state, MR, OCE->getArg(0), LC);
+      const RefState *RS = state->get<IteratorState>(MR);
+      // If found, return it.
+      if (!RS->isUnknown())
+        return state;
+      // Otherwise return what we find in the right side.
+      return handleAssign(state, MR, OCE->getArg(1), LC);
+    }
+  }
+  // Fall through if nothing matched.
+  return state;
+}
+
+// Iterate through the arguments looking for an Invalid or Undefined iterator.
+void IteratorsChecker::checkArgs(CheckerContext &C, const CallExpr *CE) const {
+  for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end();
+       I != E; ++I) {
+    checkExpr(C, *I);
+  }
+}
+
+// Get the DeclRefExpr associated with the expression.
+const DeclRefExpr *IteratorsChecker::getDeclRefExpr(const Expr *E) const {
+  // If it is a CXXConstructExpr, need to get the subexpression.
+  if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(E)) {
+    if (CE->getNumArgs()== 1) {
+      CXXConstructorDecl *CD = CE->getConstructor();
+      if (CD->isTrivial())
+        E = CE->getArg(0);
+    }
+  }
+  if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(E))
+    E = M->GetTemporaryExpr();
+  if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
+    E = ICE->getSubExpr();
+  // If it isn't one of our types, don't do anything.
+  if (getTemplateKind(E->getType()) != VectorIteratorKind)
+    return NULL;
+  return dyn_cast<DeclRefExpr>(E);
+}
+
+// Get the MemRegion associated with the expresssion.
+const MemRegion *IteratorsChecker::getRegion(ProgramStateRef state,
+    const Expr *E, const LocationContext *LC) const {
+  const DeclRefExpr *DRE = getDeclRefExpr(E);
+  if (!DRE)
+    return NULL;
+  const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl());
+  if (!VD)
+    return NULL;
+  // return the MemRegion associated with the iterator
+  return state->getRegion(VD, LC);
+}
+
+// Check the expression and if it is an iterator, generate a diagnostic
+// if the iterator is not valid.
+// FIXME: this method can generate new nodes, and subsequent logic should
+// use those nodes.  We also cannot create multiple nodes at one ProgramPoint
+// with the same tag.
+void IteratorsChecker::checkExpr(CheckerContext &C, const Expr *E) const {
+  ProgramStateRef state = C.getState();
+  const MemRegion *MR = getRegion(state, E, C.getLocationContext());
+  if (!MR)
+    return;
+
+  // Get the state associated with the iterator.
+  const RefState *RS = state->get<IteratorState>(MR);
+  if (!RS)
+    return;
+  if (RS->isInvalid()) {
+    if (ExplodedNode *N = C.addTransition()) {
+      if (!BT_Invalid)
+        // FIXME: We are eluding constness here.
+        const_cast<IteratorsChecker*>(this)->BT_Invalid = new BuiltinBug("");
+
+      std::string msg;
+      const MemberExpr *ME = RS->getMemberExpr();
+      if (ME) {
+        std::string name = ME->getMemberNameInfo().getAsString();
+        msg = "Attempt to use an iterator made invalid by call to '" +
+                                                                  name + "'";
+      }
+      else {
+        msg = "Attempt to use an iterator made invalid by copying another "
+                    "container to its container";
+      }
+
+      BugReport *R = new BugReport(*BT_Invalid, msg, N);
+      R->addRange(getDeclRefExpr(E)->getSourceRange());
+      C.EmitReport(R);
+    }
+  }
+  else if (RS->isUndefined()) {
+    if (ExplodedNode *N = C.addTransition()) {
+      if (!BT_Undefined)
+        // FIXME: We are eluding constness here.
+        const_cast<IteratorsChecker*>(this)->BT_Undefined =
+          new BuiltinBug("Use of iterator that is not defined");
+
+      BugReport *R = new BugReport(*BT_Undefined,
+                                           BT_Undefined->getDescription(), N);
+      R->addRange(getDeclRefExpr(E)->getSourceRange());
+      C.EmitReport(R);
+    }
+  }
+}
+
+// ===============================================
+// Path analysis visitor functions
+// ===============================================
+
+// For a generic Call, just check the args for bad iterators.
+void IteratorsChecker::checkPreStmt(const CallExpr *CE,
+                                    CheckerContext &C) const{
+  
+  // FIXME: These checks are to currently work around a bug
+  // in CheckerManager.
+  if (isa<CXXOperatorCallExpr>(CE))
+    return;
+  if (isa<CXXMemberCallExpr>(CE))
+    return;
+
+  checkArgs(C, CE);
+}
+
+// Handle operator calls. First, if it is operator=, check the argument,
+// and handle assigning and set target state appropriately. Otherwise, for
+// other operators, check the args for bad iterators and handle comparisons.
+void IteratorsChecker::checkPreStmt(const CXXOperatorCallExpr *OCE,
+                                    CheckerContext &C) const
+{
+  const LocationContext *LC = C.getLocationContext();
+  ProgramStateRef state = C.getState();
+  OverloadedOperatorKind Kind = OCE->getOperator();
+  if (Kind == OO_Equal) {
+    checkExpr(C, OCE->getArg(1));
+    state = handleAssign(state, OCE->getArg(0), OCE->getArg(1), LC);
+    C.addTransition(state);
+    return;
+  }
+  else {
+    checkArgs(C, OCE);
+    // If it is a compare and both are iterators, ensure that they are for
+    // the same container.
+    if (Kind == OO_EqualEqual || Kind == OO_ExclaimEqual ||
+        Kind == OO_Less || Kind == OO_LessEqual ||
+        Kind == OO_Greater || Kind == OO_GreaterEqual) {
+      const MemRegion *MR0, *MR1;
+      MR0 = getRegion(state, OCE->getArg(0), LC);
+      if (!MR0)
+        return;
+      MR1 = getRegion(state, OCE->getArg(1), LC);
+      if (!MR1)
+        return;
+      const RefState *RS0, *RS1;
+      RS0 = state->get<IteratorState>(MR0);
+      if (!RS0)
+        return;
+      RS1 = state->get<IteratorState>(MR1);
+      if (!RS1)
+        return;
+      if (RS0->getMemRegion() != RS1->getMemRegion()) {
+      if (ExplodedNode *N = C.addTransition()) {
+          if (!BT_Incompatible)
+            const_cast<IteratorsChecker*>(this)->BT_Incompatible =
+              new BuiltinBug(
+                      "Cannot compare iterators from different containers");
+
+          BugReport *R = new BugReport(*BT_Incompatible,
+                                        BT_Incompatible->getDescription(), N);
+          R->addRange(OCE->getSourceRange());
+          C.EmitReport(R);
+        }
+      }
+    }
+  }
+}
+
+// Need to handle DeclStmts to pick up initializing of iterators and to mark
+// uninitialized ones as Undefined.
+void IteratorsChecker::checkPreStmt(const DeclStmt *DS,
+                                    CheckerContext &C) const {
+  const Decl *D = *DS->decl_begin();
+  const VarDecl *VD = dyn_cast<VarDecl>(D);
+  // Only care about iterators.
+  if (getTemplateKind(VD->getType()) != VectorIteratorKind)
+    return;
+
+  // Get the MemRegion associated with the iterator and mark it as Undefined.
+  ProgramStateRef state = C.getState();
+  Loc VarLoc = state->getLValue(VD, C.getLocationContext());
+  const MemRegion *MR = VarLoc.getAsRegion();
+  if (!MR)
+    return;
+  state = state->set<IteratorState>(MR, RefState::getUndefined());
+
+  // if there is an initializer, handle marking Valid if a proper initializer
+  const Expr *InitEx = VD->getInit();
+  if (InitEx) {
+    // FIXME: This is too syntactic.  Since 'InitEx' will be analyzed first
+    // it should resolve to an SVal that we can check for validity
+    // *semantically* instead of walking through the AST.
+    if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(InitEx)) {
+      if (CE->getNumArgs() == 1) {
+        const Expr *E = CE->getArg(0);
+        if (const MaterializeTemporaryExpr *M
+                                        = dyn_cast<MaterializeTemporaryExpr>(E))
+          E = M->GetTemporaryExpr();
+        if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
+          InitEx = ICE->getSubExpr();
+        state = handleAssign(state, MR, InitEx, C.getLocationContext());
+      }
+    }
+  }
+  C.addTransition(state);
+}
+
+
+namespace { struct CalledReserved {}; }
+namespace clang { namespace ento {
+template<> struct ProgramStateTrait<CalledReserved> 
+    :  public ProgramStatePartialTrait<llvm::ImmutableSet<const MemRegion*> > {
+  static void *GDMIndex() { static int index = 0; return &index; }
+};
+}}
+
+// on a member call, first check the args for any bad iterators
+// then, check to see if it is a call to a function that will invalidate
+// the iterators
+void IteratorsChecker::checkPreStmt(const CXXMemberCallExpr *MCE,
+                                    CheckerContext &C) const {
+  // Check the arguments.
+  checkArgs(C, MCE);
+  const MemberExpr *ME = dyn_cast<MemberExpr>(MCE->getCallee());
+  if (!ME)
+    return;
+  // Make sure we have the right kind of container.
+  const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ME->getBase());
+  if (!DRE || getTemplateKind(DRE->getType()) != VectorKind)
+    return;
+  SVal tsv = C.getState()->getSVal(DRE, C.getLocationContext());
+  // Get the MemRegion associated with the container instance.
+  const MemRegion *MR = tsv.getAsRegion();
+  if (!MR)
+    return;
+  // If we are calling a function that invalidates iterators, mark them
+  // appropriately by finding matching instances.
+  ProgramStateRef state = C.getState();
+  StringRef mName = ME->getMemberDecl()->getName();
+  if (llvm::StringSwitch<bool>(mName)
+      .Cases("insert", "reserve", "push_back", true)
+      .Cases("erase", "pop_back", "clear", "resize", true)
+      .Default(false)) {
+    // If there was a 'reserve' call, assume iterators are good.
+    if (!state->contains<CalledReserved>(MR))
+      state = invalidateIterators(state, MR, ME);
+  }
+  // Keep track of instances that have called 'reserve'
+  // note: do this after we invalidate any iterators by calling 
+  // 'reserve' itself.
+  if (mName == "reserve")
+    state = state->add<CalledReserved>(MR);
+  
+  if (state != C.getState())
+    C.addTransition(state);
+}
+
diff --git a/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
new file mode 100644
index 0000000..757a4ce
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
@@ -0,0 +1,314 @@
+//=== LLVMConventionsChecker.cpp - Check LLVM codebase conventions ---*- C++ -*-
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines LLVMConventionsChecker, a bunch of small little checks
+// for checking specific coding conventions in the LLVM/Clang codebase.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/StmtVisitor.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang;
+using namespace ento;
+
+//===----------------------------------------------------------------------===//
+// Generic type checking routines.
+//===----------------------------------------------------------------------===//
+
+static bool IsLLVMStringRef(QualType T) {
+  const RecordType *RT = T->getAs<RecordType>();
+  if (!RT)
+    return false;
+
+  return StringRef(QualType(RT, 0).getAsString()) ==
+          "class StringRef";
+}
+
+/// Check whether the declaration is semantically inside the top-level
+/// namespace named by ns.
+static bool InNamespace(const Decl *D, StringRef NS) {
+  const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D->getDeclContext());
+  if (!ND)
+    return false;
+  const IdentifierInfo *II = ND->getIdentifier();
+  if (!II || !II->getName().equals(NS))
+    return false;
+  return isa<TranslationUnitDecl>(ND->getDeclContext());
+}
+
+static bool IsStdString(QualType T) {
+  if (const ElaboratedType *QT = T->getAs<ElaboratedType>())
+    T = QT->getNamedType();
+
+  const TypedefType *TT = T->getAs<TypedefType>();
+  if (!TT)
+    return false;
+
+  const TypedefNameDecl *TD = TT->getDecl();
+
+  if (!InNamespace(TD, "std"))
+    return false;
+
+  return TD->getName() == "string";
+}
+
+static bool IsClangType(const RecordDecl *RD) {
+  return RD->getName() == "Type" && InNamespace(RD, "clang");
+}
+
+static bool IsClangDecl(const RecordDecl *RD) {
+  return RD->getName() == "Decl" && InNamespace(RD, "clang");
+}
+
+static bool IsClangStmt(const RecordDecl *RD) {
+  return RD->getName() == "Stmt" && InNamespace(RD, "clang");
+}
+
+static bool IsClangAttr(const RecordDecl *RD) {
+  return RD->getName() == "Attr" && InNamespace(RD, "clang");
+}
+
+static bool IsStdVector(QualType T) {
+  const TemplateSpecializationType *TS = T->getAs<TemplateSpecializationType>();
+  if (!TS)
+    return false;
+
+  TemplateName TM = TS->getTemplateName();
+  TemplateDecl *TD = TM.getAsTemplateDecl();
+
+  if (!TD || !InNamespace(TD, "std"))
+    return false;
+
+  return TD->getName() == "vector";
+}
+
+static bool IsSmallVector(QualType T) {
+  const TemplateSpecializationType *TS = T->getAs<TemplateSpecializationType>();
+  if (!TS)
+    return false;
+
+  TemplateName TM = TS->getTemplateName();
+  TemplateDecl *TD = TM.getAsTemplateDecl();
+
+  if (!TD || !InNamespace(TD, "llvm"))
+    return false;
+
+  return TD->getName() == "SmallVector";
+}
+
+//===----------------------------------------------------------------------===//
+// CHECK: a StringRef should not be bound to a temporary std::string whose
+// lifetime is shorter than the StringRef's.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class StringRefCheckerVisitor : public StmtVisitor<StringRefCheckerVisitor> {
+  BugReporter &BR;
+  const Decl *DeclWithIssue;
+public:
+  StringRefCheckerVisitor(const Decl *declWithIssue, BugReporter &br)
+    : BR(br), DeclWithIssue(declWithIssue) {}
+  void VisitChildren(Stmt *S) {
+    for (Stmt::child_iterator I = S->child_begin(), E = S->child_end() ;
+      I != E; ++I)
+      if (Stmt *child = *I)
+        Visit(child);
+  }
+  void VisitStmt(Stmt *S) { VisitChildren(S); }
+  void VisitDeclStmt(DeclStmt *DS);
+private:
+  void VisitVarDecl(VarDecl *VD);
+};
+} // end anonymous namespace
+
+static void CheckStringRefAssignedTemporary(const Decl *D, BugReporter &BR) {
+  StringRefCheckerVisitor walker(D, BR);
+  walker.Visit(D->getBody());
+}
+
+void StringRefCheckerVisitor::VisitDeclStmt(DeclStmt *S) {
+  VisitChildren(S);
+
+  for (DeclStmt::decl_iterator I = S->decl_begin(), E = S->decl_end();I!=E; ++I)
+    if (VarDecl *VD = dyn_cast<VarDecl>(*I))
+      VisitVarDecl(VD);
+}
+
+void StringRefCheckerVisitor::VisitVarDecl(VarDecl *VD) {
+  Expr *Init = VD->getInit();
+  if (!Init)
+    return;
+
+  // Pattern match for:
+  // StringRef x = call() (where call returns std::string)
+  if (!IsLLVMStringRef(VD->getType()))
+    return;
+  ExprWithCleanups *Ex1 = dyn_cast<ExprWithCleanups>(Init);
+  if (!Ex1)
+    return;
+  CXXConstructExpr *Ex2 = dyn_cast<CXXConstructExpr>(Ex1->getSubExpr());
+  if (!Ex2 || Ex2->getNumArgs() != 1)
+    return;
+  ImplicitCastExpr *Ex3 = dyn_cast<ImplicitCastExpr>(Ex2->getArg(0));
+  if (!Ex3)
+    return;
+  CXXConstructExpr *Ex4 = dyn_cast<CXXConstructExpr>(Ex3->getSubExpr());
+  if (!Ex4 || Ex4->getNumArgs() != 1)
+    return;
+  ImplicitCastExpr *Ex5 = dyn_cast<ImplicitCastExpr>(Ex4->getArg(0));
+  if (!Ex5)
+    return;
+  CXXBindTemporaryExpr *Ex6 = dyn_cast<CXXBindTemporaryExpr>(Ex5->getSubExpr());
+  if (!Ex6 || !IsStdString(Ex6->getType()))
+    return;
+
+  // Okay, badness!  Report an error.
+  const char *desc = "StringRef should not be bound to temporary "
+                     "std::string that it outlives";
+  PathDiagnosticLocation VDLoc =
+    PathDiagnosticLocation::createBegin(VD, BR.getSourceManager());
+  BR.EmitBasicReport(DeclWithIssue, desc, "LLVM Conventions", desc,
+                     VDLoc, Init->getSourceRange());
+}
+
+//===----------------------------------------------------------------------===//
+// CHECK: Clang AST nodes should not have fields that can allocate
+//   memory.
+//===----------------------------------------------------------------------===//
+
+static bool AllocatesMemory(QualType T) {
+  return IsStdVector(T) || IsStdString(T) || IsSmallVector(T);
+}
+
+// This type checking could be sped up via dynamic programming.
+static bool IsPartOfAST(const CXXRecordDecl *R) {
+  if (IsClangStmt(R) || IsClangType(R) || IsClangDecl(R) || IsClangAttr(R))
+    return true;
+
+  for (CXXRecordDecl::base_class_const_iterator I = R->bases_begin(),
+                                                E = R->bases_end(); I!=E; ++I) {
+    CXXBaseSpecifier BS = *I;
+    QualType T = BS.getType();
+    if (const RecordType *baseT = T->getAs<RecordType>()) {
+      CXXRecordDecl *baseD = cast<CXXRecordDecl>(baseT->getDecl());
+      if (IsPartOfAST(baseD))
+        return true;
+    }
+  }
+
+  return false;
+}
+
+namespace {
+class ASTFieldVisitor {
+  SmallVector<FieldDecl*, 10> FieldChain;
+  const CXXRecordDecl *Root;
+  BugReporter &BR;
+public:
+  ASTFieldVisitor(const CXXRecordDecl *root, BugReporter &br)
+    : Root(root), BR(br) {}
+
+  void Visit(FieldDecl *D);
+  void ReportError(QualType T);
+};
+} // end anonymous namespace
+
+static void CheckASTMemory(const CXXRecordDecl *R, BugReporter &BR) {
+  if (!IsPartOfAST(R))
+    return;
+
+  for (RecordDecl::field_iterator I = R->field_begin(), E = R->field_end();
+       I != E; ++I) {
+    ASTFieldVisitor walker(R, BR);
+    walker.Visit(*I);
+  }
+}
+
+void ASTFieldVisitor::Visit(FieldDecl *D) {
+  FieldChain.push_back(D);
+
+  QualType T = D->getType();
+
+  if (AllocatesMemory(T))
+    ReportError(T);
+
+  if (const RecordType *RT = T->getAs<RecordType>()) {
+    const RecordDecl *RD = RT->getDecl()->getDefinition();
+    for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
+         I != E; ++I)
+      Visit(*I);
+  }
+
+  FieldChain.pop_back();
+}
+
+void ASTFieldVisitor::ReportError(QualType T) {
+  SmallString<1024> buf;
+  llvm::raw_svector_ostream os(buf);
+
+  os << "AST class '" << Root->getName() << "' has a field '"
+     << FieldChain.front()->getName() << "' that allocates heap memory";
+  if (FieldChain.size() > 1) {
+    os << " via the following chain: ";
+    bool isFirst = true;
+    for (SmallVectorImpl<FieldDecl*>::iterator I=FieldChain.begin(),
+         E=FieldChain.end(); I!=E; ++I) {
+      if (!isFirst)
+        os << '.';
+      else
+        isFirst = false;
+      os << (*I)->getName();
+    }
+  }
+  os << " (type " << FieldChain.back()->getType().getAsString() << ")";
+  os.flush();
+
+  // Note that this will fire for every translation unit that uses this
+  // class.  This is suboptimal, but at least scan-build will merge
+  // duplicate HTML reports.  In the future we need a unified way of merging
+  // duplicate reports across translation units.  For C++ classes we cannot
+  // just report warnings when we see an out-of-line method definition for a
+  // class, as that heuristic doesn't always work (the complete definition of
+  // the class may be in the header file, for example).
+  PathDiagnosticLocation L = PathDiagnosticLocation::createBegin(
+                               FieldChain.front(), BR.getSourceManager());
+  BR.EmitBasicReport(Root, "AST node allocates heap memory", "LLVM Conventions",
+                     os.str(), L);
+}
+
+//===----------------------------------------------------------------------===//
+// LLVMConventionsChecker
+//===----------------------------------------------------------------------===//
+
+namespace {
+class LLVMConventionsChecker : public Checker<
+                                                check::ASTDecl<CXXRecordDecl>,
+                                                check::ASTCodeBody > {
+public:
+  void checkASTDecl(const CXXRecordDecl *R, AnalysisManager& mgr,
+                    BugReporter &BR) const {
+    if (R->isCompleteDefinition())
+      CheckASTMemory(R, BR);
+  }
+
+  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
+                        BugReporter &BR) const {
+    CheckStringRefAssignedTemporary(D, BR);
+  }
+};
+}
+
+void ento::registerLLVMConventionsChecker(CheckerManager &mgr) {
+  mgr.registerChecker<LLVMConventionsChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
new file mode 100644
index 0000000..cb976e0
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
@@ -0,0 +1,681 @@
+//==--- MacOSKeychainAPIChecker.cpp ------------------------------*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This checker flags misuses of KeyChainAPI. In particular, the password data
+// allocated/returned by SecKeychainItemCopyContent,
+// SecKeychainFindGenericPassword, SecKeychainFindInternetPassword functions has
+// to be freed using a call to SecKeychainItemFreeContent.
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class MacOSKeychainAPIChecker : public Checker<check::PreStmt<CallExpr>,
+                                               check::PreStmt<ReturnStmt>,
+                                               check::PostStmt<CallExpr>,
+                                               check::EndPath,
+                                               check::DeadSymbols> {
+  mutable OwningPtr<BugType> BT;
+
+public:
+  /// AllocationState is a part of the checker specific state together with the
+  /// MemRegion corresponding to the allocated data.
+  struct AllocationState {
+    /// The index of the allocator function.
+    unsigned int AllocatorIdx;
+    SymbolRef Region;
+
+    AllocationState(const Expr *E, unsigned int Idx, SymbolRef R) :
+      AllocatorIdx(Idx),
+      Region(R) {}
+
+    bool operator==(const AllocationState &X) const {
+      return (AllocatorIdx == X.AllocatorIdx &&
+              Region == X.Region);
+    }
+
+    void Profile(llvm::FoldingSetNodeID &ID) const {
+      ID.AddInteger(AllocatorIdx);
+      ID.AddPointer(Region);
+    }
+  };
+
+  void checkPreStmt(const CallExpr *S, CheckerContext &C) const;
+  void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
+  void checkPostStmt(const CallExpr *S, CheckerContext &C) const;
+  void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
+  void checkEndPath(CheckerContext &C) const;
+
+private:
+  typedef std::pair<SymbolRef, const AllocationState*> AllocationPair;
+  typedef llvm::SmallVector<AllocationPair, 2> AllocationPairVec;
+
+  enum APIKind {
+    /// Denotes functions tracked by this checker.
+    ValidAPI = 0,
+    /// The functions commonly/mistakenly used in place of the given API.
+    ErrorAPI = 1,
+    /// The functions which may allocate the data. These are tracked to reduce
+    /// the false alarm rate.
+    PossibleAPI = 2
+  };
+  /// Stores the information about the allocator and deallocator functions -
+  /// these are the functions the checker is tracking.
+  struct ADFunctionInfo {
+    const char* Name;
+    unsigned int Param;
+    unsigned int DeallocatorIdx;
+    APIKind Kind;
+  };
+  static const unsigned InvalidIdx = 100000;
+  static const unsigned FunctionsToTrackSize = 8;
+  static const ADFunctionInfo FunctionsToTrack[FunctionsToTrackSize];
+  /// The value, which represents no error return value for allocator functions.
+  static const unsigned NoErr = 0;
+
+  /// Given the function name, returns the index of the allocator/deallocator
+  /// function.
+  static unsigned getTrackedFunctionIndex(StringRef Name, bool IsAllocator);
+
+  inline void initBugType() const {
+    if (!BT)
+      BT.reset(new BugType("Improper use of SecKeychain API", "Mac OS API"));
+  }
+
+  void generateDeallocatorMismatchReport(const AllocationPair &AP,
+                                         const Expr *ArgExpr,
+                                         CheckerContext &C) const;
+
+  /// Find the allocation site for Sym on the path leading to the node N.
+  const Stmt *getAllocationSite(const ExplodedNode *N, SymbolRef Sym,
+                                CheckerContext &C) const;
+
+  BugReport *generateAllocatedDataNotReleasedReport(const AllocationPair &AP,
+                                                    ExplodedNode *N,
+                                                    CheckerContext &C) const;
+
+  /// Check if RetSym evaluates to an error value in the current state.
+  bool definitelyReturnedError(SymbolRef RetSym,
+                               ProgramStateRef State,
+                               SValBuilder &Builder,
+                               bool noError = false) const;
+
+  /// Check if RetSym evaluates to a NoErr value in the current state.
+  bool definitelyDidnotReturnError(SymbolRef RetSym,
+                                   ProgramStateRef State,
+                                   SValBuilder &Builder) const {
+    return definitelyReturnedError(RetSym, State, Builder, true);
+  }
+                                                 
+  /// Mark an AllocationPair interesting for diagnostic reporting.
+  void markInteresting(BugReport *R, const AllocationPair &AP) const {
+    R->markInteresting(AP.first);
+    R->markInteresting(AP.second->Region);
+  }
+
+  /// The bug visitor which allows us to print extra diagnostics along the
+  /// BugReport path. For example, showing the allocation site of the leaked
+  /// region.
+  class SecKeychainBugVisitor
+    : public BugReporterVisitorImpl<SecKeychainBugVisitor> {
+  protected:
+    // The allocated region symbol tracked by the main analysis.
+    SymbolRef Sym;
+
+  public:
+    SecKeychainBugVisitor(SymbolRef S) : Sym(S) {}
+    virtual ~SecKeychainBugVisitor() {}
+
+    void Profile(llvm::FoldingSetNodeID &ID) const {
+      static int X = 0;
+      ID.AddPointer(&X);
+      ID.AddPointer(Sym);
+    }
+
+    PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+                                   const ExplodedNode *PrevN,
+                                   BugReporterContext &BRC,
+                                   BugReport &BR);
+  };
+};
+}
+
+/// ProgramState traits to store the currently allocated (and not yet freed)
+/// symbols. This is a map from the allocated content symbol to the
+/// corresponding AllocationState.
+typedef llvm::ImmutableMap<SymbolRef,
+                       MacOSKeychainAPIChecker::AllocationState> AllocatedSetTy;
+
+namespace { struct AllocatedData {}; }
+namespace clang { namespace ento {
+template<> struct ProgramStateTrait<AllocatedData>
+    :  public ProgramStatePartialTrait<AllocatedSetTy > {
+  static void *GDMIndex() { static int index = 0; return &index; }
+};
+}}
+
+static bool isEnclosingFunctionParam(const Expr *E) {
+  E = E->IgnoreParenCasts();
+  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+    const ValueDecl *VD = DRE->getDecl();
+    if (isa<ImplicitParamDecl>(VD) || isa<ParmVarDecl>(VD))
+      return true;
+  }
+  return false;
+}
+
+const MacOSKeychainAPIChecker::ADFunctionInfo
+  MacOSKeychainAPIChecker::FunctionsToTrack[FunctionsToTrackSize] = {
+    {"SecKeychainItemCopyContent", 4, 3, ValidAPI},                       // 0
+    {"SecKeychainFindGenericPassword", 6, 3, ValidAPI},                   // 1
+    {"SecKeychainFindInternetPassword", 13, 3, ValidAPI},                 // 2
+    {"SecKeychainItemFreeContent", 1, InvalidIdx, ValidAPI},              // 3
+    {"SecKeychainItemCopyAttributesAndData", 5, 5, ValidAPI},             // 4
+    {"SecKeychainItemFreeAttributesAndData", 1, InvalidIdx, ValidAPI},    // 5
+    {"free", 0, InvalidIdx, ErrorAPI},                                    // 6
+    {"CFStringCreateWithBytesNoCopy", 1, InvalidIdx, PossibleAPI},        // 7
+};
+
+unsigned MacOSKeychainAPIChecker::getTrackedFunctionIndex(StringRef Name,
+                                                          bool IsAllocator) {
+  for (unsigned I = 0; I < FunctionsToTrackSize; ++I) {
+    ADFunctionInfo FI = FunctionsToTrack[I];
+    if (FI.Name != Name)
+      continue;
+    // Make sure the function is of the right type (allocator vs deallocator).
+    if (IsAllocator && (FI.DeallocatorIdx == InvalidIdx))
+      return InvalidIdx;
+    if (!IsAllocator && (FI.DeallocatorIdx != InvalidIdx))
+      return InvalidIdx;
+
+    return I;
+  }
+  // The function is not tracked.
+  return InvalidIdx;
+}
+
+static bool isBadDeallocationArgument(const MemRegion *Arg) {
+  if (!Arg)
+    return false;
+  if (isa<AllocaRegion>(Arg) ||
+      isa<BlockDataRegion>(Arg) ||
+      isa<TypedRegion>(Arg)) {
+    return true;
+  }
+  return false;
+}
+
+/// Given the address expression, retrieve the value it's pointing to. Assume
+/// that value is itself an address, and return the corresponding symbol.
+static SymbolRef getAsPointeeSymbol(const Expr *Expr,
+                                    CheckerContext &C) {
+  ProgramStateRef State = C.getState();
+  SVal ArgV = State->getSVal(Expr, C.getLocationContext());
+
+  if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(&ArgV)) {
+    StoreManager& SM = C.getStoreManager();
+    SymbolRef sym = SM.getBinding(State->getStore(), *X).getAsLocSymbol();
+    if (sym)
+      return sym;
+  }
+  return 0;
+}
+
+// When checking for error code, we need to consider the following cases:
+// 1) noErr / [0]
+// 2) someErr / [1, inf]
+// 3) unknown
+// If noError, returns true iff (1).
+// If !noError, returns true iff (2).
+bool MacOSKeychainAPIChecker::definitelyReturnedError(SymbolRef RetSym,
+                                                      ProgramStateRef State,
+                                                      SValBuilder &Builder,
+                                                      bool noError) const {
+  DefinedOrUnknownSVal NoErrVal = Builder.makeIntVal(NoErr,
+    Builder.getSymbolManager().getType(RetSym));
+  DefinedOrUnknownSVal NoErr = Builder.evalEQ(State, NoErrVal,
+                                                     nonloc::SymbolVal(RetSym));
+  ProgramStateRef ErrState = State->assume(NoErr, noError);
+  if (ErrState == State) {
+    return true;
+  }
+
+  return false;
+}
+
+// Report deallocator mismatch. Remove the region from tracking - reporting a
+// missing free error after this one is redundant.
+void MacOSKeychainAPIChecker::
+  generateDeallocatorMismatchReport(const AllocationPair &AP,
+                                    const Expr *ArgExpr,
+                                    CheckerContext &C) const {
+  ProgramStateRef State = C.getState();
+  State = State->remove<AllocatedData>(AP.first);
+  ExplodedNode *N = C.addTransition(State);
+
+  if (!N)
+    return;
+  initBugType();
+  SmallString<80> sbuf;
+  llvm::raw_svector_ostream os(sbuf);
+  unsigned int PDeallocIdx =
+               FunctionsToTrack[AP.second->AllocatorIdx].DeallocatorIdx;
+
+  os << "Deallocator doesn't match the allocator: '"
+     << FunctionsToTrack[PDeallocIdx].Name << "' should be used.";
+  BugReport *Report = new BugReport(*BT, os.str(), N);
+  Report->addVisitor(new SecKeychainBugVisitor(AP.first));
+  Report->addRange(ArgExpr->getSourceRange());
+  markInteresting(Report, AP);
+  C.EmitReport(Report);
+}
+
+void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
+                                           CheckerContext &C) const {
+  unsigned idx = InvalidIdx;
+  ProgramStateRef State = C.getState();
+
+  StringRef funName = C.getCalleeName(CE);
+  if (funName.empty())
+    return;
+
+  // If it is a call to an allocator function, it could be a double allocation.
+  idx = getTrackedFunctionIndex(funName, true);
+  if (idx != InvalidIdx) {
+    const Expr *ArgExpr = CE->getArg(FunctionsToTrack[idx].Param);
+    if (SymbolRef V = getAsPointeeSymbol(ArgExpr, C))
+      if (const AllocationState *AS = State->get<AllocatedData>(V)) {
+        if (!definitelyReturnedError(AS->Region, State, C.getSValBuilder())) {
+          // Remove the value from the state. The new symbol will be added for
+          // tracking when the second allocator is processed in checkPostStmt().
+          State = State->remove<AllocatedData>(V);
+          ExplodedNode *N = C.addTransition(State);
+          if (!N)
+            return;
+          initBugType();
+          SmallString<128> sbuf;
+          llvm::raw_svector_ostream os(sbuf);
+          unsigned int DIdx = FunctionsToTrack[AS->AllocatorIdx].DeallocatorIdx;
+          os << "Allocated data should be released before another call to "
+              << "the allocator: missing a call to '"
+              << FunctionsToTrack[DIdx].Name
+              << "'.";
+          BugReport *Report = new BugReport(*BT, os.str(), N);
+          Report->addVisitor(new SecKeychainBugVisitor(V));
+          Report->addRange(ArgExpr->getSourceRange());
+          Report->markInteresting(AS->Region);
+          C.EmitReport(Report);
+        }
+      }
+    return;
+  }
+
+  // Is it a call to one of deallocator functions?
+  idx = getTrackedFunctionIndex(funName, false);
+  if (idx == InvalidIdx)
+    return;
+
+  // Check the argument to the deallocator.
+  const Expr *ArgExpr = CE->getArg(FunctionsToTrack[idx].Param);
+  SVal ArgSVal = State->getSVal(ArgExpr, C.getLocationContext());
+
+  // Undef is reported by another checker.
+  if (ArgSVal.isUndef())
+    return;
+
+  SymbolRef ArgSM = ArgSVal.getAsLocSymbol();
+
+  // If the argument is coming from the heap, globals, or unknown, do not
+  // report it.
+  bool RegionArgIsBad = false;
+  if (!ArgSM) {
+    if (!isBadDeallocationArgument(ArgSVal.getAsRegion()))
+      return;
+    RegionArgIsBad = true;
+  }
+
+  // Is the argument to the call being tracked?
+  const AllocationState *AS = State->get<AllocatedData>(ArgSM);
+  if (!AS && FunctionsToTrack[idx].Kind != ValidAPI) {
+    return;
+  }
+  // If trying to free data which has not been allocated yet, report as a bug.
+  // TODO: We might want a more precise diagnostic for double free
+  // (that would involve tracking all the freed symbols in the checker state).
+  if (!AS || RegionArgIsBad) {
+    // It is possible that this is a false positive - the argument might
+    // have entered as an enclosing function parameter.
+    if (isEnclosingFunctionParam(ArgExpr))
+      return;
+
+    ExplodedNode *N = C.addTransition(State);
+    if (!N)
+      return;
+    initBugType();
+    BugReport *Report = new BugReport(*BT,
+        "Trying to free data which has not been allocated.", N);
+    Report->addRange(ArgExpr->getSourceRange());
+    if (AS)
+      Report->markInteresting(AS->Region);
+    C.EmitReport(Report);
+    return;
+  }
+
+  // Process functions which might deallocate.
+  if (FunctionsToTrack[idx].Kind == PossibleAPI) {
+
+    if (funName == "CFStringCreateWithBytesNoCopy") {
+      const Expr *DeallocatorExpr = CE->getArg(5)->IgnoreParenCasts();
+      // NULL ~ default deallocator, so warn.
+      if (DeallocatorExpr->isNullPointerConstant(C.getASTContext(),
+          Expr::NPC_ValueDependentIsNotNull)) {
+        const AllocationPair AP = std::make_pair(ArgSM, AS);
+        generateDeallocatorMismatchReport(AP, ArgExpr, C);
+        return;
+      }
+      // One of the default allocators, so warn.
+      if (const DeclRefExpr *DE = dyn_cast<DeclRefExpr>(DeallocatorExpr)) {
+        StringRef DeallocatorName = DE->getFoundDecl()->getName();
+        if (DeallocatorName == "kCFAllocatorDefault" ||
+            DeallocatorName == "kCFAllocatorSystemDefault" ||
+            DeallocatorName == "kCFAllocatorMalloc") {
+          const AllocationPair AP = std::make_pair(ArgSM, AS);
+          generateDeallocatorMismatchReport(AP, ArgExpr, C);
+          return;
+        }
+        // If kCFAllocatorNull, which does not deallocate, we still have to
+        // find the deallocator. Otherwise, assume that the user had written a
+        // custom deallocator which does the right thing.
+        if (DE->getFoundDecl()->getName() != "kCFAllocatorNull") {
+          State = State->remove<AllocatedData>(ArgSM);
+          C.addTransition(State);
+          return;
+        }
+      }
+    }
+    return;
+  }
+
+  // The call is deallocating a value we previously allocated, so remove it
+  // from the next state.
+  State = State->remove<AllocatedData>(ArgSM);
+
+  // Check if the proper deallocator is used.
+  unsigned int PDeallocIdx = FunctionsToTrack[AS->AllocatorIdx].DeallocatorIdx;
+  if (PDeallocIdx != idx || (FunctionsToTrack[idx].Kind == ErrorAPI)) {
+    const AllocationPair AP = std::make_pair(ArgSM, AS);
+    generateDeallocatorMismatchReport(AP, ArgExpr, C);
+    return;
+  }
+
+  // If the buffer can be null and the return status can be an error,
+  // report a bad call to free.
+  if (State->assume(cast<DefinedSVal>(ArgSVal), false) &&
+      !definitelyDidnotReturnError(AS->Region, State, C.getSValBuilder())) {
+    ExplodedNode *N = C.addTransition(State);
+    if (!N)
+      return;
+    initBugType();
+    BugReport *Report = new BugReport(*BT,
+        "Only call free if a valid (non-NULL) buffer was returned.", N);
+    Report->addVisitor(new SecKeychainBugVisitor(ArgSM));
+    Report->addRange(ArgExpr->getSourceRange());
+    Report->markInteresting(AS->Region);
+    C.EmitReport(Report);
+    return;
+  }
+
+  C.addTransition(State);
+}
+
+void MacOSKeychainAPIChecker::checkPostStmt(const CallExpr *CE,
+                                            CheckerContext &C) const {
+  ProgramStateRef State = C.getState();
+  StringRef funName = C.getCalleeName(CE);
+
+  // If a value has been allocated, add it to the set for tracking.
+  unsigned idx = getTrackedFunctionIndex(funName, true);
+  if (idx == InvalidIdx)
+    return;
+
+  const Expr *ArgExpr = CE->getArg(FunctionsToTrack[idx].Param);
+  // If the argument entered as an enclosing function parameter, skip it to
+  // avoid false positives.
+  if (isEnclosingFunctionParam(ArgExpr) &&
+      C.getLocationContext()->getParent() == 0)
+    return;
+
+  if (SymbolRef V = getAsPointeeSymbol(ArgExpr, C)) {
+    // If the argument points to something that's not a symbolic region, it
+    // can be:
+    //  - unknown (cannot reason about it)
+    //  - undefined (already reported by other checker)
+    //  - constant (null - should not be tracked,
+    //              other constant will generate a compiler warning)
+    //  - goto (should be reported by other checker)
+
+    // The call return value symbol should stay alive for as long as the
+    // allocated value symbol, since our diagnostics depend on the value
+    // returned by the call. Ex: Data should only be freed if noErr was
+    // returned during allocation.)
+    SymbolRef RetStatusSymbol =
+      State->getSVal(CE, C.getLocationContext()).getAsSymbol();
+    C.getSymbolManager().addSymbolDependency(V, RetStatusSymbol);
+
+    // Track the allocated value in the checker state.
+    State = State->set<AllocatedData>(V, AllocationState(ArgExpr, idx,
+                                                         RetStatusSymbol));
+    assert(State);
+    C.addTransition(State);
+  }
+}
+
+void MacOSKeychainAPIChecker::checkPreStmt(const ReturnStmt *S,
+                                           CheckerContext &C) const {
+  const Expr *retExpr = S->getRetValue();
+  if (!retExpr)
+    return;
+
+  // If inside inlined call, skip it.
+  const LocationContext *LC = C.getLocationContext();
+  if (LC->getParent() != 0)
+    return;
+
+  // Check  if the value is escaping through the return.
+  ProgramStateRef state = C.getState();
+  SymbolRef sym = state->getSVal(retExpr, LC).getAsLocSymbol();
+  if (!sym)
+    return;
+  state = state->remove<AllocatedData>(sym);
+
+  // Proceed from the new state.
+  C.addTransition(state);
+}
+
+// TODO: This logic is the same as in Malloc checker.
+const Stmt *
+MacOSKeychainAPIChecker::getAllocationSite(const ExplodedNode *N,
+                                           SymbolRef Sym,
+                                           CheckerContext &C) const {
+  const LocationContext *LeakContext = N->getLocationContext();
+  // Walk the ExplodedGraph backwards and find the first node that referred to
+  // the tracked symbol.
+  const ExplodedNode *AllocNode = N;
+
+  while (N) {
+    if (!N->getState()->get<AllocatedData>(Sym))
+      break;
+    // Allocation node, is the last node in the current context in which the
+    // symbol was tracked.
+    if (N->getLocationContext() == LeakContext)
+      AllocNode = N;
+    N = N->pred_empty() ? NULL : *(N->pred_begin());
+  }
+
+  ProgramPoint P = AllocNode->getLocation();
+  if (!isa<StmtPoint>(P))
+    return 0;
+  return cast<clang::PostStmt>(P).getStmt();
+}
+
+BugReport *MacOSKeychainAPIChecker::
+  generateAllocatedDataNotReleasedReport(const AllocationPair &AP,
+                                         ExplodedNode *N,
+                                         CheckerContext &C) const {
+  const ADFunctionInfo &FI = FunctionsToTrack[AP.second->AllocatorIdx];
+  initBugType();
+  SmallString<70> sbuf;
+  llvm::raw_svector_ostream os(sbuf);
+  os << "Allocated data is not released: missing a call to '"
+      << FunctionsToTrack[FI.DeallocatorIdx].Name << "'.";
+
+  // Most bug reports are cached at the location where they occurred.
+  // With leaks, we want to unique them by the location where they were
+  // allocated, and only report a single path.
+  PathDiagnosticLocation LocUsedForUniqueing;
+  if (const Stmt *AllocStmt = getAllocationSite(N, AP.first, C))
+    LocUsedForUniqueing = PathDiagnosticLocation::createBegin(AllocStmt,
+                            C.getSourceManager(), N->getLocationContext());
+
+  BugReport *Report = new BugReport(*BT, os.str(), N, LocUsedForUniqueing);
+  Report->addVisitor(new SecKeychainBugVisitor(AP.first));
+  markInteresting(Report, AP);
+  return Report;
+}
+
+void MacOSKeychainAPIChecker::checkDeadSymbols(SymbolReaper &SR,
+                                               CheckerContext &C) const {
+  ProgramStateRef State = C.getState();
+  AllocatedSetTy ASet = State->get<AllocatedData>();
+  if (ASet.isEmpty())
+    return;
+
+  bool Changed = false;
+  AllocationPairVec Errors;
+  for (AllocatedSetTy::iterator I = ASet.begin(), E = ASet.end(); I != E; ++I) {
+    if (SR.isLive(I->first))
+      continue;
+
+    Changed = true;
+    State = State->remove<AllocatedData>(I->first);
+    // If the allocated symbol is null or if the allocation call might have
+    // returned an error, do not report.
+    if (State->getSymVal(I->first) ||
+        definitelyReturnedError(I->second.Region, State, C.getSValBuilder()))
+      continue;
+    Errors.push_back(std::make_pair(I->first, &I->second));
+  }
+  if (!Changed) {
+    // Generate the new, cleaned up state.
+    C.addTransition(State);
+    return;
+  }
+
+  static SimpleProgramPointTag Tag("MacOSKeychainAPIChecker : DeadSymbolsLeak");
+  ExplodedNode *N = C.addTransition(C.getState(), C.getPredecessor(), &Tag);
+
+  // Generate the error reports.
+  for (AllocationPairVec::iterator I = Errors.begin(), E = Errors.end();
+                                                       I != E; ++I) {
+    C.EmitReport(generateAllocatedDataNotReleasedReport(*I, N, C));
+  }
+
+  // Generate the new, cleaned up state.
+  C.addTransition(State, N);
+}
+
+// TODO: Remove this after we ensure that checkDeadSymbols are always called.
+void MacOSKeychainAPIChecker::checkEndPath(CheckerContext &C) const {
+  ProgramStateRef state = C.getState();
+
+  // If inside inlined call, skip it.
+  if (C.getLocationContext()->getParent() != 0)
+    return;
+
+  AllocatedSetTy AS = state->get<AllocatedData>();
+  if (AS.isEmpty())
+    return;
+
+  // Anything which has been allocated but not freed (nor escaped) will be
+  // found here, so report it.
+  bool Changed = false;
+  AllocationPairVec Errors;
+  for (AllocatedSetTy::iterator I = AS.begin(), E = AS.end(); I != E; ++I ) {
+    Changed = true;
+    state = state->remove<AllocatedData>(I->first);
+    // If the allocated symbol is null or if error code was returned at
+    // allocation, do not report.
+    if (state->getSymVal(I.getKey()) ||
+        definitelyReturnedError(I->second.Region, state,
+                                C.getSValBuilder())) {
+      continue;
+    }
+    Errors.push_back(std::make_pair(I->first, &I->second));
+  }
+
+  // If no change, do not generate a new state.
+  if (!Changed) {
+    C.addTransition(state);
+    return;
+  }
+
+  static SimpleProgramPointTag Tag("MacOSKeychainAPIChecker : EndPathLeak");
+  ExplodedNode *N = C.addTransition(C.getState(), C.getPredecessor(), &Tag);
+
+  // Generate the error reports.
+  for (AllocationPairVec::iterator I = Errors.begin(), E = Errors.end();
+                                                       I != E; ++I) {
+    C.EmitReport(generateAllocatedDataNotReleasedReport(*I, N, C));
+  }
+
+  C.addTransition(state, N);
+}
+
+
+PathDiagnosticPiece *MacOSKeychainAPIChecker::SecKeychainBugVisitor::VisitNode(
+                                                      const ExplodedNode *N,
+                                                      const ExplodedNode *PrevN,
+                                                      BugReporterContext &BRC,
+                                                      BugReport &BR) {
+  const AllocationState *AS = N->getState()->get<AllocatedData>(Sym);
+  if (!AS)
+    return 0;
+  const AllocationState *ASPrev = PrevN->getState()->get<AllocatedData>(Sym);
+  if (ASPrev)
+    return 0;
+
+  // (!ASPrev && AS) ~ We started tracking symbol in node N, it must be the
+  // allocation site.
+  const CallExpr *CE = cast<CallExpr>(cast<StmtPoint>(N->getLocation())
+                                                            .getStmt());
+  const FunctionDecl *funDecl = CE->getDirectCallee();
+  assert(funDecl && "We do not support indirect function calls as of now.");
+  StringRef funName = funDecl->getName();
+
+  // Get the expression of the corresponding argument.
+  unsigned Idx = getTrackedFunctionIndex(funName, true);
+  assert(Idx != InvalidIdx && "This should be a call to an allocator.");
+  const Expr *ArgExpr = CE->getArg(FunctionsToTrack[Idx].Param);
+  PathDiagnosticLocation Pos(ArgExpr, BRC.getSourceManager(),
+                             N->getLocationContext());
+  return new PathDiagnosticEventPiece(Pos, "Data is allocated here.");
+}
+
+void ento::registerMacOSKeychainAPIChecker(CheckerManager &mgr) {
+  mgr.registerChecker<MacOSKeychainAPIChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
new file mode 100644
index 0000000..cfdb55d
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
@@ -0,0 +1,116 @@
+// MacOSXAPIChecker.h - Checks proper use of various MacOS X APIs --*- C++ -*-//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines MacOSXAPIChecker, which is an assortment of checks on calls
+// to various, widely used Mac OS X functions.
+//
+// FIXME: What's currently in BasicObjCFoundationChecks.cpp should be migrated
+// to here, using the new Checker interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class MacOSXAPIChecker : public Checker< check::PreStmt<CallExpr> > {
+  mutable OwningPtr<BugType> BT_dispatchOnce;
+
+public:
+  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
+
+  void CheckDispatchOnce(CheckerContext &C, const CallExpr *CE,
+                         StringRef FName) const;
+
+  typedef void (MacOSXAPIChecker::*SubChecker)(CheckerContext &,
+                                               const CallExpr *,
+                                               StringRef FName) const;
+};
+} //end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// dispatch_once and dispatch_once_f
+//===----------------------------------------------------------------------===//
+
+void MacOSXAPIChecker::CheckDispatchOnce(CheckerContext &C, const CallExpr *CE,
+                                         StringRef FName) const {
+  if (CE->getNumArgs() < 1)
+    return;
+
+  // Check if the first argument is stack allocated.  If so, issue a warning
+  // because that's likely to be bad news.
+  ProgramStateRef state = C.getState();
+  const MemRegion *R =
+    state->getSVal(CE->getArg(0), C.getLocationContext()).getAsRegion();
+  if (!R || !isa<StackSpaceRegion>(R->getMemorySpace()))
+    return;
+
+  ExplodedNode *N = C.generateSink(state);
+  if (!N)
+    return;
+
+  if (!BT_dispatchOnce)
+    BT_dispatchOnce.reset(new BugType("Improper use of 'dispatch_once'",
+                                      "Mac OS X API"));
+
+  SmallString<256> S;
+  llvm::raw_svector_ostream os(S);
+  os << "Call to '" << FName << "' uses";
+  if (const VarRegion *VR = dyn_cast<VarRegion>(R))
+    os << " the local variable '" << VR->getDecl()->getName() << '\'';
+  else
+    os << " stack allocated memory";
+  os << " for the predicate value.  Using such transient memory for "
+        "the predicate is potentially dangerous.";
+  if (isa<VarRegion>(R) && isa<StackLocalsSpaceRegion>(R->getMemorySpace()))
+    os << "  Perhaps you intended to declare the variable as 'static'?";
+
+  BugReport *report = new BugReport(*BT_dispatchOnce, os.str(), N);
+  report->addRange(CE->getArg(0)->getSourceRange());
+  C.EmitReport(report);
+}
+
+//===----------------------------------------------------------------------===//
+// Central dispatch function.
+//===----------------------------------------------------------------------===//
+
+void MacOSXAPIChecker::checkPreStmt(const CallExpr *CE,
+                                    CheckerContext &C) const {
+  StringRef Name = C.getCalleeName(CE);
+  if (Name.empty())
+    return;
+
+  SubChecker SC =
+    llvm::StringSwitch<SubChecker>(Name)
+      .Cases("dispatch_once", "dispatch_once_f",
+             &MacOSXAPIChecker::CheckDispatchOnce)
+      .Default(NULL);
+
+  if (SC)
+    (this->*SC)(C, CE, Name);
+}
+
+//===----------------------------------------------------------------------===//
+// Registration.
+//===----------------------------------------------------------------------===//
+
+void ento::registerMacOSXAPIChecker(CheckerManager &mgr) {
+  mgr.registerChecker<MacOSXAPIChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/Makefile b/clang/lib/StaticAnalyzer/Checkers/Makefile
new file mode 100644
index 0000000..2582908
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/Makefile
@@ -0,0 +1,24 @@
+##===- clang/lib/Checker/Makefile --------------------------*- Makefile -*-===##
+# 
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+# 
+##===----------------------------------------------------------------------===##
+#
+# This implements analyses built on top of source-level CFGs. 
+#
+##===----------------------------------------------------------------------===##
+
+CLANG_LEVEL := ../../..
+LIBRARYNAME := clangStaticAnalyzerCheckers
+
+BUILT_SOURCES = Checkers.inc
+TABLEGEN_INC_FILES_COMMON = 1
+
+include $(CLANG_LEVEL)/Makefile
+
+$(ObjDir)/Checkers.inc.tmp : Checkers.td $(PROJ_SRC_DIR)/$(CLANG_LEVEL)/include/clang/StaticAnalyzer/Checkers/CheckerBase.td $(CLANG_TBLGEN) $(ObjDir)/.dir
+	$(Echo) "Building Clang SA Checkers tables with tblgen"
+	$(Verb) $(ClangTableGen) -gen-clang-sa-checkers -I $(PROJ_SRC_DIR)/$(CLANG_LEVEL)/include -o $(call SYSPATH, $@) $<
diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
new file mode 100644
index 0000000..8bce88a
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -0,0 +1,1463 @@
+//=== MallocChecker.cpp - A malloc/free checker -------------------*- C++ -*--//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines malloc/free checker, which checks for potential memory
+// leaks, double free, and use-after-free problems.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "InterCheckerAPI.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/STLExtras.h"
+#include <climits>
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class RefState {
+  enum Kind { AllocateUnchecked, AllocateFailed, Released, Escaped,
+              Relinquished } K;
+  const Stmt *S;
+
+public:
+  RefState(Kind k, const Stmt *s) : K(k), S(s) {}
+
+  bool isAllocated() const { return K == AllocateUnchecked; }
+  bool isReleased() const { return K == Released; }
+
+  const Stmt *getStmt() const { return S; }
+
+  bool operator==(const RefState &X) const {
+    return K == X.K && S == X.S;
+  }
+
+  static RefState getAllocateUnchecked(const Stmt *s) { 
+    return RefState(AllocateUnchecked, s); 
+  }
+  static RefState getAllocateFailed() {
+    return RefState(AllocateFailed, 0);
+  }
+  static RefState getReleased(const Stmt *s) { return RefState(Released, s); }
+  static RefState getEscaped(const Stmt *s) { return RefState(Escaped, s); }
+  static RefState getRelinquished(const Stmt *s) {
+    return RefState(Relinquished, s);
+  }
+
+  void Profile(llvm::FoldingSetNodeID &ID) const {
+    ID.AddInteger(K);
+    ID.AddPointer(S);
+  }
+};
+
+struct ReallocPair {
+  SymbolRef ReallocatedSym;
+  bool IsFreeOnFailure;
+  ReallocPair(SymbolRef S, bool F) : ReallocatedSym(S), IsFreeOnFailure(F) {}
+  void Profile(llvm::FoldingSetNodeID &ID) const {
+    ID.AddInteger(IsFreeOnFailure);
+    ID.AddPointer(ReallocatedSym);
+  }
+  bool operator==(const ReallocPair &X) const {
+    return ReallocatedSym == X.ReallocatedSym &&
+           IsFreeOnFailure == X.IsFreeOnFailure;
+  }
+};
+
+typedef std::pair<const Stmt*, const MemRegion*> LeakInfo;
+
+class MallocChecker : public Checker<check::DeadSymbols,
+                                     check::EndPath,
+                                     check::PreStmt<ReturnStmt>,
+                                     check::PreStmt<CallExpr>,
+                                     check::PostStmt<CallExpr>,
+                                     check::PostStmt<BlockExpr>,
+                                     check::Location,
+                                     check::Bind,
+                                     eval::Assume,
+                                     check::RegionChanges>
+{
+  mutable OwningPtr<BugType> BT_DoubleFree;
+  mutable OwningPtr<BugType> BT_Leak;
+  mutable OwningPtr<BugType> BT_UseFree;
+  mutable OwningPtr<BugType> BT_BadFree;
+  mutable IdentifierInfo *II_malloc, *II_free, *II_realloc, *II_calloc,
+                         *II_valloc, *II_reallocf, *II_strndup, *II_strdup;
+
+public:
+  MallocChecker() : II_malloc(0), II_free(0), II_realloc(0), II_calloc(0),
+                    II_valloc(0), II_reallocf(0), II_strndup(0), II_strdup(0) {}
+
+  /// In pessimistic mode, the checker assumes that it does not know which
+  /// functions might free the memory.
+  struct ChecksFilter {
+    DefaultBool CMallocPessimistic;
+    DefaultBool CMallocOptimistic;
+  };
+
+  ChecksFilter Filter;
+
+  void checkPreStmt(const CallExpr *S, CheckerContext &C) const;
+  void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
+  void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
+  void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
+  void checkEndPath(CheckerContext &C) const;
+  void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
+  ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond,
+                            bool Assumption) const;
+  void checkLocation(SVal l, bool isLoad, const Stmt *S,
+                     CheckerContext &C) const;
+  void checkBind(SVal location, SVal val, const Stmt*S,
+                 CheckerContext &C) const;
+  ProgramStateRef
+  checkRegionChanges(ProgramStateRef state,
+                     const StoreManager::InvalidatedSymbols *invalidated,
+                     ArrayRef<const MemRegion *> ExplicitRegions,
+                     ArrayRef<const MemRegion *> Regions,
+                     const CallOrObjCMessage *Call) const;
+  bool wantsRegionChangeUpdate(ProgramStateRef state) const {
+    return true;
+  }
+
+private:
+  void initIdentifierInfo(ASTContext &C) const;
+
+  /// Check if this is one of the functions which can allocate/reallocate memory 
+  /// pointed to by one of its arguments.
+  bool isMemFunction(const FunctionDecl *FD, ASTContext &C) const;
+
+  static ProgramStateRef MallocMemReturnsAttr(CheckerContext &C,
+                                              const CallExpr *CE,
+                                              const OwnershipAttr* Att);
+  static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE,
+                                     const Expr *SizeEx, SVal Init,
+                                     ProgramStateRef state) {
+    return MallocMemAux(C, CE,
+                        state->getSVal(SizeEx, C.getLocationContext()),
+                        Init, state);
+  }
+
+  static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE,
+                                     SVal SizeEx, SVal Init,
+                                     ProgramStateRef state);
+
+  /// Update the RefState to reflect the new memory allocation.
+  static ProgramStateRef MallocUpdateRefState(CheckerContext &C,
+                                              const CallExpr *CE,
+                                              ProgramStateRef state);
+
+  ProgramStateRef FreeMemAttr(CheckerContext &C, const CallExpr *CE,
+                              const OwnershipAttr* Att) const;
+  ProgramStateRef FreeMemAux(CheckerContext &C, const CallExpr *CE,
+                                 ProgramStateRef state, unsigned Num,
+                                 bool Hold) const;
+
+  ProgramStateRef ReallocMem(CheckerContext &C, const CallExpr *CE,
+                             bool FreesMemOnFailure) const;
+  static ProgramStateRef CallocMem(CheckerContext &C, const CallExpr *CE);
+  
+  bool checkEscape(SymbolRef Sym, const Stmt *S, CheckerContext &C) const;
+  bool checkUseAfterFree(SymbolRef Sym, CheckerContext &C,
+                         const Stmt *S = 0) const;
+
+  /// Check if the function is not known to us. So, for example, we could
+  /// conservatively assume it can free/reallocate it's pointer arguments.
+  bool doesNotFreeMemory(const CallOrObjCMessage *Call,
+                         ProgramStateRef State) const;
+
+  static bool SummarizeValue(raw_ostream &os, SVal V);
+  static bool SummarizeRegion(raw_ostream &os, const MemRegion *MR);
+  void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange range) const;
+
+  /// Find the location of the allocation for Sym on the path leading to the
+  /// exploded node N.
+  LeakInfo getAllocationSite(const ExplodedNode *N, SymbolRef Sym,
+                             CheckerContext &C) const;
+
+  void reportLeak(SymbolRef Sym, ExplodedNode *N, CheckerContext &C) const;
+
+  /// The bug visitor which allows us to print extra diagnostics along the
+  /// BugReport path. For example, showing the allocation site of the leaked
+  /// region.
+  class MallocBugVisitor : public BugReporterVisitorImpl<MallocBugVisitor> {
+  protected:
+    enum NotificationMode {
+      Normal,
+      ReallocationFailed
+    };
+
+    // The allocated region symbol tracked by the main analysis.
+    SymbolRef Sym;
+
+     // The mode we are in, i.e. what kind of diagnostics will be emitted.
+     NotificationMode Mode;
+
+     // A symbol from when the primary region should have been reallocated.
+     SymbolRef FailedReallocSymbol;
+
+   public:
+     MallocBugVisitor(SymbolRef S)
+       : Sym(S), Mode(Normal), FailedReallocSymbol(0) {}
+
+    virtual ~MallocBugVisitor() {}
+
+    void Profile(llvm::FoldingSetNodeID &ID) const {
+      static int X = 0;
+      ID.AddPointer(&X);
+      ID.AddPointer(Sym);
+    }
+
+    inline bool isAllocated(const RefState *S, const RefState *SPrev,
+                            const Stmt *Stmt) {
+      // Did not track -> allocated. Other state (released) -> allocated.
+      return (Stmt && isa<CallExpr>(Stmt) &&
+              (S && S->isAllocated()) && (!SPrev || !SPrev->isAllocated()));
+    }
+
+    inline bool isReleased(const RefState *S, const RefState *SPrev,
+                           const Stmt *Stmt) {
+      // Did not track -> released. Other state (allocated) -> released.
+      return (Stmt && isa<CallExpr>(Stmt) &&
+              (S && S->isReleased()) && (!SPrev || !SPrev->isReleased()));
+    }
+
+    inline bool isReallocFailedCheck(const RefState *S, const RefState *SPrev,
+                                     const Stmt *Stmt) {
+      // If the expression is not a call, and the state change is
+      // released -> allocated, it must be the realloc return value
+      // check. If we have to handle more cases here, it might be cleaner just
+      // to track this extra bit in the state itself.
+      return ((!Stmt || !isa<CallExpr>(Stmt)) &&
+              (S && S->isAllocated()) && (SPrev && !SPrev->isAllocated()));
+    }
+
+    PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+                                   const ExplodedNode *PrevN,
+                                   BugReporterContext &BRC,
+                                   BugReport &BR);
+  private:
+    class StackHintGeneratorForReallocationFailed
+        : public StackHintGeneratorForSymbol {
+    public:
+      StackHintGeneratorForReallocationFailed(SymbolRef S, StringRef M)
+        : StackHintGeneratorForSymbol(S, M) {}
+
+      virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex) {
+        SmallString<200> buf;
+        llvm::raw_svector_ostream os(buf);
+
+        os << "Reallocation of ";
+        // Printed parameters start at 1, not 0.
+        printOrdinal(++ArgIndex, os);
+        os << " parameter failed";
+
+        return os.str();
+      }
+
+      virtual std::string getMessageForReturn(const CallExpr *CallExpr) {
+        return "Reallocation of returned value failed";
+      }
+    };
+  };
+};
+} // end anonymous namespace
+
+typedef llvm::ImmutableMap<SymbolRef, RefState> RegionStateTy;
+typedef llvm::ImmutableMap<SymbolRef, ReallocPair > ReallocMap;
+class RegionState {};
+class ReallocPairs {};
+namespace clang {
+namespace ento {
+  template <>
+  struct ProgramStateTrait<RegionState> 
+    : public ProgramStatePartialTrait<RegionStateTy> {
+    static void *GDMIndex() { static int x; return &x; }
+  };
+
+  template <>
+  struct ProgramStateTrait<ReallocPairs>
+    : public ProgramStatePartialTrait<ReallocMap> {
+    static void *GDMIndex() { static int x; return &x; }
+  };
+}
+}
+
+namespace {
+class StopTrackingCallback : public SymbolVisitor {
+  ProgramStateRef state;
+public:
+  StopTrackingCallback(ProgramStateRef st) : state(st) {}
+  ProgramStateRef getState() const { return state; }
+
+  bool VisitSymbol(SymbolRef sym) {
+    state = state->remove<RegionState>(sym);
+    return true;
+  }
+};
+} // end anonymous namespace
+
+void MallocChecker::initIdentifierInfo(ASTContext &Ctx) const {
+  if (!II_malloc)
+    II_malloc = &Ctx.Idents.get("malloc");
+  if (!II_free)
+    II_free = &Ctx.Idents.get("free");
+  if (!II_realloc)
+    II_realloc = &Ctx.Idents.get("realloc");
+  if (!II_reallocf)
+    II_reallocf = &Ctx.Idents.get("reallocf");
+  if (!II_calloc)
+    II_calloc = &Ctx.Idents.get("calloc");
+  if (!II_valloc)
+    II_valloc = &Ctx.Idents.get("valloc");
+  if (!II_strdup)
+    II_strdup = &Ctx.Idents.get("strdup");
+  if (!II_strndup)
+    II_strndup = &Ctx.Idents.get("strndup");
+}
+
+bool MallocChecker::isMemFunction(const FunctionDecl *FD, ASTContext &C) const {
+  if (!FD)
+    return false;
+  IdentifierInfo *FunI = FD->getIdentifier();
+  if (!FunI)
+    return false;
+
+  initIdentifierInfo(C);
+
+  if (FunI == II_malloc || FunI == II_free || FunI == II_realloc ||
+      FunI == II_reallocf || FunI == II_calloc || FunI == II_valloc ||
+      FunI == II_strdup || FunI == II_strndup)
+    return true;
+
+  if (Filter.CMallocOptimistic && FD->hasAttrs() &&
+      FD->specific_attr_begin<OwnershipAttr>() !=
+          FD->specific_attr_end<OwnershipAttr>())
+    return true;
+
+
+  return false;
+}
+
+void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const {
+  const FunctionDecl *FD = C.getCalleeDecl(CE);
+  if (!FD)
+    return;
+
+  initIdentifierInfo(C.getASTContext());
+  IdentifierInfo *FunI = FD->getIdentifier();
+  if (!FunI)
+    return;
+
+  ProgramStateRef State = C.getState();
+  if (FunI == II_malloc || FunI == II_valloc) {
+    if (CE->getNumArgs() < 1)
+      return;
+    State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State);
+  } else if (FunI == II_realloc) {
+    State = ReallocMem(C, CE, false);
+  } else if (FunI == II_reallocf) {
+    State = ReallocMem(C, CE, true);
+  } else if (FunI == II_calloc) {
+    State = CallocMem(C, CE);
+  } else if (FunI == II_free) {
+    State = FreeMemAux(C, CE, C.getState(), 0, false);
+  } else if (FunI == II_strdup) {
+    State = MallocUpdateRefState(C, CE, State);
+  } else if (FunI == II_strndup) {
+    State = MallocUpdateRefState(C, CE, State);
+  } else if (Filter.CMallocOptimistic) {
+    // Check all the attributes, if there are any.
+    // There can be multiple of these attributes.
+    if (FD->hasAttrs())
+      for (specific_attr_iterator<OwnershipAttr>
+          i = FD->specific_attr_begin<OwnershipAttr>(),
+          e = FD->specific_attr_end<OwnershipAttr>();
+          i != e; ++i) {
+        switch ((*i)->getOwnKind()) {
+        case OwnershipAttr::Returns:
+          State = MallocMemReturnsAttr(C, CE, *i);
+          break;
+        case OwnershipAttr::Takes:
+        case OwnershipAttr::Holds:
+          State = FreeMemAttr(C, CE, *i);
+          break;
+        }
+      }
+  }
+  C.addTransition(State);
+}
+
+ProgramStateRef MallocChecker::MallocMemReturnsAttr(CheckerContext &C,
+                                                    const CallExpr *CE,
+                                                    const OwnershipAttr* Att) {
+  if (Att->getModule() != "malloc")
+    return 0;
+
+  OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
+  if (I != E) {
+    return MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), C.getState());
+  }
+  return MallocMemAux(C, CE, UnknownVal(), UndefinedVal(), C.getState());
+}
+
+ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
+                                           const CallExpr *CE,
+                                           SVal Size, SVal Init,
+                                           ProgramStateRef state) {
+  // Get the return value.
+  SVal retVal = state->getSVal(CE, C.getLocationContext());
+
+  // We expect the malloc functions to return a pointer.
+  if (!isa<Loc>(retVal))
+    return 0;
+
+  // Fill the region with the initialization value.
+  state = state->bindDefault(retVal, Init);
+
+  // Set the region's extent equal to the Size parameter.
+  const SymbolicRegion *R =
+      dyn_cast_or_null<SymbolicRegion>(retVal.getAsRegion());
+  if (!R)
+    return 0;
+  if (isa<DefinedOrUnknownSVal>(Size)) {
+    SValBuilder &svalBuilder = C.getSValBuilder();
+    DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder);
+    DefinedOrUnknownSVal DefinedSize = cast<DefinedOrUnknownSVal>(Size);
+    DefinedOrUnknownSVal extentMatchesSize =
+        svalBuilder.evalEQ(state, Extent, DefinedSize);
+
+    state = state->assume(extentMatchesSize, true);
+    assert(state);
+  }
+  
+  return MallocUpdateRefState(C, CE, state);
+}
+
+ProgramStateRef MallocChecker::MallocUpdateRefState(CheckerContext &C,
+                                                    const CallExpr *CE,
+                                                    ProgramStateRef state) {
+  // Get the return value.
+  SVal retVal = state->getSVal(CE, C.getLocationContext());
+
+  // We expect the malloc functions to return a pointer.
+  if (!isa<Loc>(retVal))
+    return 0;
+
+  SymbolRef Sym = retVal.getAsLocSymbol();
+  assert(Sym);
+
+  // Set the symbol's state to Allocated.
+  return state->set<RegionState>(Sym, RefState::getAllocateUnchecked(CE));
+
+}
+
+ProgramStateRef MallocChecker::FreeMemAttr(CheckerContext &C,
+                                           const CallExpr *CE,
+                                           const OwnershipAttr* Att) const {
+  if (Att->getModule() != "malloc")
+    return 0;
+
+  ProgramStateRef State = C.getState();
+
+  for (OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
+       I != E; ++I) {
+    ProgramStateRef StateI = FreeMemAux(C, CE, State, *I,
+                               Att->getOwnKind() == OwnershipAttr::Holds);
+    if (StateI)
+      State = StateI;
+  }
+  return State;
+}
+
+ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
+                                          const CallExpr *CE,
+                                          ProgramStateRef state,
+                                          unsigned Num,
+                                          bool Hold) const {
+  if (CE->getNumArgs() < (Num + 1))
+    return 0;
+
+  const Expr *ArgExpr = CE->getArg(Num);
+  SVal ArgVal = state->getSVal(ArgExpr, C.getLocationContext());
+  if (!isa<DefinedOrUnknownSVal>(ArgVal))
+    return 0;
+  DefinedOrUnknownSVal location = cast<DefinedOrUnknownSVal>(ArgVal);
+
+  // Check for null dereferences.
+  if (!isa<Loc>(location))
+    return 0;
+
+  // The explicit NULL case, no operation is performed.
+  ProgramStateRef notNullState, nullState;
+  llvm::tie(notNullState, nullState) = state->assume(location);
+  if (nullState && !notNullState)
+    return 0;
+
+  // Unknown values could easily be okay
+  // Undefined values are handled elsewhere
+  if (ArgVal.isUnknownOrUndef())
+    return 0;
+
+  const MemRegion *R = ArgVal.getAsRegion();
+  
+  // Nonlocs can't be freed, of course.
+  // Non-region locations (labels and fixed addresses) also shouldn't be freed.
+  if (!R) {
+    ReportBadFree(C, ArgVal, ArgExpr->getSourceRange());
+    return 0;
+  }
+  
+  R = R->StripCasts();
+  
+  // Blocks might show up as heap data, but should not be free()d
+  if (isa<BlockDataRegion>(R)) {
+    ReportBadFree(C, ArgVal, ArgExpr->getSourceRange());
+    return 0;
+  }
+  
+  const MemSpaceRegion *MS = R->getMemorySpace();
+  
+  // Parameters, locals, statics, and globals shouldn't be freed.
+  if (!(isa<UnknownSpaceRegion>(MS) || isa<HeapSpaceRegion>(MS))) {
+    // FIXME: at the time this code was written, malloc() regions were
+    // represented by conjured symbols, which are all in UnknownSpaceRegion.
+    // This means that there isn't actually anything from HeapSpaceRegion
+    // that should be freed, even though we allow it here.
+    // Of course, free() can work on memory allocated outside the current
+    // function, so UnknownSpaceRegion is always a possibility.
+    // False negatives are better than false positives.
+    
+    ReportBadFree(C, ArgVal, ArgExpr->getSourceRange());
+    return 0;
+  }
+  
+  const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R);
+  // Various cases could lead to non-symbol values here.
+  // For now, ignore them.
+  if (!SR)
+    return 0;
+
+  SymbolRef Sym = SR->getSymbol();
+  const RefState *RS = state->get<RegionState>(Sym);
+
+  // If the symbol has not been tracked, return. This is possible when free() is
+  // called on a pointer that does not get its pointee directly from malloc(). 
+  // Full support of this requires inter-procedural analysis.
+  if (!RS)
+    return 0;
+
+  // Check double free.
+  if (RS->isReleased()) {
+    if (ExplodedNode *N = C.generateSink()) {
+      if (!BT_DoubleFree)
+        BT_DoubleFree.reset(
+          new BugType("Double free", "Memory Error"));
+      BugReport *R = new BugReport(*BT_DoubleFree, 
+                        "Attempt to free released memory", N);
+      R->addRange(ArgExpr->getSourceRange());
+      R->markInteresting(Sym);
+      R->addVisitor(new MallocBugVisitor(Sym));
+      C.EmitReport(R);
+    }
+    return 0;
+  }
+
+  // Normal free.
+  if (Hold)
+    return state->set<RegionState>(Sym, RefState::getRelinquished(CE));
+  return state->set<RegionState>(Sym, RefState::getReleased(CE));
+}
+
+bool MallocChecker::SummarizeValue(raw_ostream &os, SVal V) {
+  if (nonloc::ConcreteInt *IntVal = dyn_cast<nonloc::ConcreteInt>(&V))
+    os << "an integer (" << IntVal->getValue() << ")";
+  else if (loc::ConcreteInt *ConstAddr = dyn_cast<loc::ConcreteInt>(&V))
+    os << "a constant address (" << ConstAddr->getValue() << ")";
+  else if (loc::GotoLabel *Label = dyn_cast<loc::GotoLabel>(&V))
+    os << "the address of the label '" << Label->getLabel()->getName() << "'";
+  else
+    return false;
+  
+  return true;
+}
+
+bool MallocChecker::SummarizeRegion(raw_ostream &os,
+                                    const MemRegion *MR) {
+  switch (MR->getKind()) {
+  case MemRegion::FunctionTextRegionKind: {
+    const FunctionDecl *FD = cast<FunctionTextRegion>(MR)->getDecl();
+    if (FD)
+      os << "the address of the function '" << *FD << '\'';
+    else
+      os << "the address of a function";
+    return true;
+  }
+  case MemRegion::BlockTextRegionKind:
+    os << "block text";
+    return true;
+  case MemRegion::BlockDataRegionKind:
+    // FIXME: where the block came from?
+    os << "a block";
+    return true;
+  default: {
+    const MemSpaceRegion *MS = MR->getMemorySpace();
+    
+    if (isa<StackLocalsSpaceRegion>(MS)) {
+      const VarRegion *VR = dyn_cast<VarRegion>(MR);
+      const VarDecl *VD;
+      if (VR)
+        VD = VR->getDecl();
+      else
+        VD = NULL;
+      
+      if (VD)
+        os << "the address of the local variable '" << VD->getName() << "'";
+      else
+        os << "the address of a local stack variable";
+      return true;
+    }
+
+    if (isa<StackArgumentsSpaceRegion>(MS)) {
+      const VarRegion *VR = dyn_cast<VarRegion>(MR);
+      const VarDecl *VD;
+      if (VR)
+        VD = VR->getDecl();
+      else
+        VD = NULL;
+      
+      if (VD)
+        os << "the address of the parameter '" << VD->getName() << "'";
+      else
+        os << "the address of a parameter";
+      return true;
+    }
+
+    if (isa<GlobalsSpaceRegion>(MS)) {
+      const VarRegion *VR = dyn_cast<VarRegion>(MR);
+      const VarDecl *VD;
+      if (VR)
+        VD = VR->getDecl();
+      else
+        VD = NULL;
+      
+      if (VD) {
+        if (VD->isStaticLocal())
+          os << "the address of the static variable '" << VD->getName() << "'";
+        else
+          os << "the address of the global variable '" << VD->getName() << "'";
+      } else
+        os << "the address of a global variable";
+      return true;
+    }
+
+    return false;
+  }
+  }
+}
+
+void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal,
+                                  SourceRange range) const {
+  if (ExplodedNode *N = C.generateSink()) {
+    if (!BT_BadFree)
+      BT_BadFree.reset(new BugType("Bad free", "Memory Error"));
+    
+    SmallString<100> buf;
+    llvm::raw_svector_ostream os(buf);
+    
+    const MemRegion *MR = ArgVal.getAsRegion();
+    if (MR) {
+      while (const ElementRegion *ER = dyn_cast<ElementRegion>(MR))
+        MR = ER->getSuperRegion();
+      
+      // Special case for alloca()
+      if (isa<AllocaRegion>(MR))
+        os << "Argument to free() was allocated by alloca(), not malloc()";
+      else {
+        os << "Argument to free() is ";
+        if (SummarizeRegion(os, MR))
+          os << ", which is not memory allocated by malloc()";
+        else
+          os << "not memory allocated by malloc()";
+      }
+    } else {
+      os << "Argument to free() is ";
+      if (SummarizeValue(os, ArgVal))
+        os << ", which is not memory allocated by malloc()";
+      else
+        os << "not memory allocated by malloc()";
+    }
+    
+    BugReport *R = new BugReport(*BT_BadFree, os.str(), N);
+    R->markInteresting(MR);
+    R->addRange(range);
+    C.EmitReport(R);
+  }
+}
+
+ProgramStateRef MallocChecker::ReallocMem(CheckerContext &C,
+                                          const CallExpr *CE,
+                                          bool FreesOnFail) const {
+  if (CE->getNumArgs() < 2)
+    return 0;
+
+  ProgramStateRef state = C.getState();
+  const Expr *arg0Expr = CE->getArg(0);
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal Arg0Val = state->getSVal(arg0Expr, LCtx);
+  if (!isa<DefinedOrUnknownSVal>(Arg0Val))
+    return 0;
+  DefinedOrUnknownSVal arg0Val = cast<DefinedOrUnknownSVal>(Arg0Val);
+
+  SValBuilder &svalBuilder = C.getSValBuilder();
+
+  DefinedOrUnknownSVal PtrEQ =
+    svalBuilder.evalEQ(state, arg0Val, svalBuilder.makeNull());
+
+  // Get the size argument. If there is no size arg then give up.
+  const Expr *Arg1 = CE->getArg(1);
+  if (!Arg1)
+    return 0;
+
+  // Get the value of the size argument.
+  SVal Arg1ValG = state->getSVal(Arg1, LCtx);
+  if (!isa<DefinedOrUnknownSVal>(Arg1ValG))
+    return 0;
+  DefinedOrUnknownSVal Arg1Val = cast<DefinedOrUnknownSVal>(Arg1ValG);
+
+  // Compare the size argument to 0.
+  DefinedOrUnknownSVal SizeZero =
+    svalBuilder.evalEQ(state, Arg1Val,
+                       svalBuilder.makeIntValWithPtrWidth(0, false));
+
+  ProgramStateRef StatePtrIsNull, StatePtrNotNull;
+  llvm::tie(StatePtrIsNull, StatePtrNotNull) = state->assume(PtrEQ);
+  ProgramStateRef StateSizeIsZero, StateSizeNotZero;
+  llvm::tie(StateSizeIsZero, StateSizeNotZero) = state->assume(SizeZero);
+  // We only assume exceptional states if they are definitely true; if the
+  // state is under-constrained, assume regular realloc behavior.
+  bool PrtIsNull = StatePtrIsNull && !StatePtrNotNull;
+  bool SizeIsZero = StateSizeIsZero && !StateSizeNotZero;
+
+  // If the ptr is NULL and the size is not 0, the call is equivalent to 
+  // malloc(size).
+  if ( PrtIsNull && !SizeIsZero) {
+    ProgramStateRef stateMalloc = MallocMemAux(C, CE, CE->getArg(1),
+                                               UndefinedVal(), StatePtrIsNull);
+    return stateMalloc;
+  }
+
+  if (PrtIsNull && SizeIsZero)
+    return 0;
+
+  // Get the from and to pointer symbols as in toPtr = realloc(fromPtr, size).
+  assert(!PrtIsNull);
+  SymbolRef FromPtr = arg0Val.getAsSymbol();
+  SVal RetVal = state->getSVal(CE, LCtx);
+  SymbolRef ToPtr = RetVal.getAsSymbol();
+  if (!FromPtr || !ToPtr)
+    return 0;
+
+  // If the size is 0, free the memory.
+  if (SizeIsZero)
+    if (ProgramStateRef stateFree = FreeMemAux(C, CE, StateSizeIsZero,0,false)){
+      // The semantics of the return value are:
+      // If size was equal to 0, either NULL or a pointer suitable to be passed
+      // to free() is returned.
+      stateFree = stateFree->set<ReallocPairs>(ToPtr,
+                                            ReallocPair(FromPtr, FreesOnFail));
+      C.getSymbolManager().addSymbolDependency(ToPtr, FromPtr);
+      return stateFree;
+    }
+
+  // Default behavior.
+  if (ProgramStateRef stateFree = FreeMemAux(C, CE, state, 0, false)) {
+    // FIXME: We should copy the content of the original buffer.
+    ProgramStateRef stateRealloc = MallocMemAux(C, CE, CE->getArg(1),
+                                                UnknownVal(), stateFree);
+    if (!stateRealloc)
+      return 0;
+    stateRealloc = stateRealloc->set<ReallocPairs>(ToPtr,
+                                            ReallocPair(FromPtr, FreesOnFail));
+    C.getSymbolManager().addSymbolDependency(ToPtr, FromPtr);
+    return stateRealloc;
+  }
+  return 0;
+}
+
+ProgramStateRef MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE){
+  if (CE->getNumArgs() < 2)
+    return 0;
+
+  ProgramStateRef state = C.getState();
+  SValBuilder &svalBuilder = C.getSValBuilder();
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal count = state->getSVal(CE->getArg(0), LCtx);
+  SVal elementSize = state->getSVal(CE->getArg(1), LCtx);
+  SVal TotalSize = svalBuilder.evalBinOp(state, BO_Mul, count, elementSize,
+                                        svalBuilder.getContext().getSizeType());  
+  SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy);
+
+  return MallocMemAux(C, CE, TotalSize, zeroVal, state);
+}
+
+LeakInfo
+MallocChecker::getAllocationSite(const ExplodedNode *N, SymbolRef Sym,
+                                 CheckerContext &C) const {
+  const LocationContext *LeakContext = N->getLocationContext();
+  // Walk the ExplodedGraph backwards and find the first node that referred to
+  // the tracked symbol.
+  const ExplodedNode *AllocNode = N;
+  const MemRegion *ReferenceRegion = 0;
+
+  while (N) {
+    ProgramStateRef State = N->getState();
+    if (!State->get<RegionState>(Sym))
+      break;
+
+    // Find the most recent expression bound to the symbol in the current
+    // context.
+    if (!ReferenceRegion) {
+      if (const MemRegion *MR = C.getLocationRegionIfPostStore(N)) {
+        SVal Val = State->getSVal(MR);
+        if (Val.getAsLocSymbol() == Sym)
+          ReferenceRegion = MR;
+      }
+    }
+
+    // Allocation node, is the last node in the current context in which the
+    // symbol was tracked.
+    if (N->getLocationContext() == LeakContext)
+      AllocNode = N;
+    N = N->pred_empty() ? NULL : *(N->pred_begin());
+  }
+
+  ProgramPoint P = AllocNode->getLocation();
+  const Stmt *AllocationStmt = 0;
+  if (isa<StmtPoint>(P))
+    AllocationStmt = cast<StmtPoint>(P).getStmt();
+
+  return LeakInfo(AllocationStmt, ReferenceRegion);
+}
+
+void MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N,
+                               CheckerContext &C) const {
+  assert(N);
+  if (!BT_Leak) {
+    BT_Leak.reset(new BugType("Memory leak", "Memory Error"));
+    // Leaks should not be reported if they are post-dominated by a sink:
+    // (1) Sinks are higher importance bugs.
+    // (2) NoReturnFunctionChecker uses sink nodes to represent paths ending
+    //     with __noreturn functions such as assert() or exit(). We choose not
+    //     to report leaks on such paths.
+    BT_Leak->setSuppressOnSink(true);
+  }
+
+  // Most bug reports are cached at the location where they occurred.
+  // With leaks, we want to unique them by the location where they were
+  // allocated, and only report a single path.
+  PathDiagnosticLocation LocUsedForUniqueing;
+  const Stmt *AllocStmt = 0;
+  const MemRegion *Region = 0;
+  llvm::tie(AllocStmt, Region) = getAllocationSite(N, Sym, C);
+  if (AllocStmt)
+    LocUsedForUniqueing = PathDiagnosticLocation::createBegin(AllocStmt,
+                            C.getSourceManager(), N->getLocationContext());
+
+  SmallString<200> buf;
+  llvm::raw_svector_ostream os(buf);
+  os << "Memory is never released; potential leak";
+  if (Region) {
+    os << " of memory pointed to by '";
+    Region->dumpPretty(os);
+    os <<'\'';
+  }
+
+  BugReport *R = new BugReport(*BT_Leak, os.str(), N, LocUsedForUniqueing);
+  R->markInteresting(Sym);
+  R->addVisitor(new MallocBugVisitor(Sym));
+  C.EmitReport(R);
+}
+
+void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper,
+                                     CheckerContext &C) const
+{
+  if (!SymReaper.hasDeadSymbols())
+    return;
+
+  ProgramStateRef state = C.getState();
+  RegionStateTy RS = state->get<RegionState>();
+  RegionStateTy::Factory &F = state->get_context<RegionState>();
+
+  bool generateReport = false;
+  llvm::SmallVector<SymbolRef, 2> Errors;
+  for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
+    if (SymReaper.isDead(I->first)) {
+      if (I->second.isAllocated()) {
+        generateReport = true;
+        Errors.push_back(I->first);
+      }
+      // Remove the dead symbol from the map.
+      RS = F.remove(RS, I->first);
+
+    }
+  }
+  
+  // Cleanup the Realloc Pairs Map.
+  ReallocMap RP = state->get<ReallocPairs>();
+  for (ReallocMap::iterator I = RP.begin(), E = RP.end(); I != E; ++I) {
+    if (SymReaper.isDead(I->first) ||
+        SymReaper.isDead(I->second.ReallocatedSym)) {
+      state = state->remove<ReallocPairs>(I->first);
+    }
+  }
+
+  // Generate leak node.
+  static SimpleProgramPointTag Tag("MallocChecker : DeadSymbolsLeak");
+  ExplodedNode *N = C.addTransition(C.getState(), C.getPredecessor(), &Tag);
+
+  if (generateReport) {
+    for (llvm::SmallVector<SymbolRef, 2>::iterator
+         I = Errors.begin(), E = Errors.end(); I != E; ++I) {
+      reportLeak(*I, N, C);
+    }
+  }
+  C.addTransition(state->set<RegionState>(RS), N);
+}
+
+void MallocChecker::checkEndPath(CheckerContext &C) const {
+  ProgramStateRef state = C.getState();
+  RegionStateTy M = state->get<RegionState>();
+
+  // If inside inlined call, skip it.
+  if (C.getLocationContext()->getParent() != 0)
+    return;
+
+  for (RegionStateTy::iterator I = M.begin(), E = M.end(); I != E; ++I) {
+    RefState RS = I->second;
+    if (RS.isAllocated()) {
+      ExplodedNode *N = C.addTransition(state);
+      if (N)
+        reportLeak(I->first, N, C);
+    }
+  }
+}
+
+bool MallocChecker::checkEscape(SymbolRef Sym, const Stmt *S,
+                                CheckerContext &C) const {
+  ProgramStateRef state = C.getState();
+  const RefState *RS = state->get<RegionState>(Sym);
+  if (!RS)
+    return false;
+
+  if (RS->isAllocated()) {
+    state = state->set<RegionState>(Sym, RefState::getEscaped(S));
+    C.addTransition(state);
+    return true;
+  }
+  return false;
+}
+
+void MallocChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
+  if (isMemFunction(C.getCalleeDecl(CE), C.getASTContext()))
+    return;
+
+  // Check use after free, when a freed pointer is passed to a call.
+  ProgramStateRef State = C.getState();
+  for (CallExpr::const_arg_iterator I = CE->arg_begin(),
+                                    E = CE->arg_end(); I != E; ++I) {
+    const Expr *A = *I;
+    if (A->getType().getTypePtr()->isAnyPointerType()) {
+      SymbolRef Sym = State->getSVal(A, C.getLocationContext()).getAsSymbol();
+      if (!Sym)
+        continue;
+      if (checkUseAfterFree(Sym, C, A))
+        return;
+    }
+  }
+}
+
+void MallocChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const {
+  const Expr *E = S->getRetValue();
+  if (!E)
+    return;
+
+  // Check if we are returning a symbol.
+  SVal RetVal = C.getState()->getSVal(E, C.getLocationContext());
+  SymbolRef Sym = RetVal.getAsSymbol();
+  if (!Sym)
+    // If we are returning a field of the allocated struct or an array element,
+    // the callee could still free the memory.
+    // TODO: This logic should be a part of generic symbol escape callback.
+    if (const MemRegion *MR = RetVal.getAsRegion())
+      if (isa<FieldRegion>(MR) || isa<ElementRegion>(MR))
+        if (const SymbolicRegion *BMR =
+              dyn_cast<SymbolicRegion>(MR->getBaseRegion()))
+          Sym = BMR->getSymbol();
+  if (!Sym)
+    return;
+
+  // Check if we are returning freed memory.
+  if (checkUseAfterFree(Sym, C, E))
+    return;
+
+  // If this function body is not inlined, check if the symbol is escaping.
+  if (C.getLocationContext()->getParent() == 0)
+    checkEscape(Sym, E, C);
+}
+
+// TODO: Blocks should be either inlined or should call invalidate regions
+// upon invocation. After that's in place, special casing here will not be 
+// needed.
+void MallocChecker::checkPostStmt(const BlockExpr *BE,
+                                  CheckerContext &C) const {
+
+  // Scan the BlockDecRefExprs for any object the retain count checker
+  // may be tracking.
+  if (!BE->getBlockDecl()->hasCaptures())
+    return;
+
+  ProgramStateRef state = C.getState();
+  const BlockDataRegion *R =
+    cast<BlockDataRegion>(state->getSVal(BE,
+                                         C.getLocationContext()).getAsRegion());
+
+  BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
+                                            E = R->referenced_vars_end();
+
+  if (I == E)
+    return;
+
+  SmallVector<const MemRegion*, 10> Regions;
+  const LocationContext *LC = C.getLocationContext();
+  MemRegionManager &MemMgr = C.getSValBuilder().getRegionManager();
+
+  for ( ; I != E; ++I) {
+    const VarRegion *VR = *I;
+    if (VR->getSuperRegion() == R) {
+      VR = MemMgr.getVarRegion(VR->getDecl(), LC);
+    }
+    Regions.push_back(VR);
+  }
+
+  state =
+    state->scanReachableSymbols<StopTrackingCallback>(Regions.data(),
+                                    Regions.data() + Regions.size()).getState();
+  C.addTransition(state);
+}
+
+bool MallocChecker::checkUseAfterFree(SymbolRef Sym, CheckerContext &C,
+                                      const Stmt *S) const {
+  assert(Sym);
+  const RefState *RS = C.getState()->get<RegionState>(Sym);
+  if (RS && RS->isReleased()) {
+    if (ExplodedNode *N = C.generateSink()) {
+      if (!BT_UseFree)
+        BT_UseFree.reset(new BugType("Use-after-free", "Memory Error"));
+
+      BugReport *R = new BugReport(*BT_UseFree,
+                                   "Use of memory after it is freed",N);
+      if (S)
+        R->addRange(S->getSourceRange());
+      R->markInteresting(Sym);
+      R->addVisitor(new MallocBugVisitor(Sym));
+      C.EmitReport(R);
+      return true;
+    }
+  }
+  return false;
+}
+
+// Check if the location is a freed symbolic region.
+void MallocChecker::checkLocation(SVal l, bool isLoad, const Stmt *S,
+                                  CheckerContext &C) const {
+  SymbolRef Sym = l.getLocSymbolInBase();
+  if (Sym)
+    checkUseAfterFree(Sym, C);
+}
+
+//===----------------------------------------------------------------------===//
+// Check various ways a symbol can be invalidated.
+// TODO: This logic (the next 3 functions) is copied/similar to the
+// RetainRelease checker. We might want to factor this out.
+//===----------------------------------------------------------------------===//
+
+// Stop tracking symbols when a value escapes as a result of checkBind.
+// A value escapes in three possible cases:
+// (1) we are binding to something that is not a memory region.
+// (2) we are binding to a memregion that does not have stack storage
+// (3) we are binding to a memregion with stack storage that the store
+//     does not understand.
+void MallocChecker::checkBind(SVal loc, SVal val, const Stmt *S,
+                              CheckerContext &C) const {
+  // Are we storing to something that causes the value to "escape"?
+  bool escapes = true;
+  ProgramStateRef state = C.getState();
+
+  if (loc::MemRegionVal *regionLoc = dyn_cast<loc::MemRegionVal>(&loc)) {
+    escapes = !regionLoc->getRegion()->hasStackStorage();
+
+    if (!escapes) {
+      // To test (3), generate a new state with the binding added.  If it is
+      // the same state, then it escapes (since the store cannot represent
+      // the binding).
+      escapes = (state == (state->bindLoc(*regionLoc, val)));
+    }
+    if (!escapes) {
+      // Case 4: We do not currently model what happens when a symbol is
+      // assigned to a struct field, so be conservative here and let the symbol
+      // go. TODO: This could definitely be improved upon.
+      escapes = !isa<VarRegion>(regionLoc->getRegion());
+    }
+  }
+
+  // If our store can represent the binding and we aren't storing to something
+  // that doesn't have local storage then just return and have the simulation
+  // state continue as is.
+  if (!escapes)
+      return;
+
+  // Otherwise, find all symbols referenced by 'val' that we are tracking
+  // and stop tracking them.
+  state = state->scanReachableSymbols<StopTrackingCallback>(val).getState();
+  C.addTransition(state);
+}
+
+// If a symbolic region is assumed to NULL (or another constant), stop tracking
+// it - assuming that allocation failed on this path.
+ProgramStateRef MallocChecker::evalAssume(ProgramStateRef state,
+                                              SVal Cond,
+                                              bool Assumption) const {
+  RegionStateTy RS = state->get<RegionState>();
+  for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
+    // If the symbol is assumed to NULL or another constant, this will
+    // return an APSInt*.
+    if (state->getSymVal(I.getKey()))
+      state = state->remove<RegionState>(I.getKey());
+  }
+
+  // Realloc returns 0 when reallocation fails, which means that we should
+  // restore the state of the pointer being reallocated.
+  ReallocMap RP = state->get<ReallocPairs>();
+  for (ReallocMap::iterator I = RP.begin(), E = RP.end(); I != E; ++I) {
+    // If the symbol is assumed to NULL or another constant, this will
+    // return an APSInt*.
+    if (state->getSymVal(I.getKey())) {
+      SymbolRef ReallocSym = I.getData().ReallocatedSym;
+      const RefState *RS = state->get<RegionState>(ReallocSym);
+      if (RS) {
+        if (RS->isReleased() && ! I.getData().IsFreeOnFailure)
+          state = state->set<RegionState>(ReallocSym,
+                             RefState::getAllocateUnchecked(RS->getStmt()));
+      }
+      state = state->remove<ReallocPairs>(I.getKey());
+    }
+  }
+
+  return state;
+}
+
+// Check if the function is known to us. So, for example, we could
+// conservatively assume it can free/reallocate it's pointer arguments.
+// (We assume that the pointers cannot escape through calls to system
+// functions not handled by this checker.)
+bool MallocChecker::doesNotFreeMemory(const CallOrObjCMessage *Call,
+                                      ProgramStateRef State) const {
+  if (!Call)
+    return false;
+
+  // For now, assume that any C++ call can free memory.
+  // TODO: If we want to be more optimistic here, we'll need to make sure that
+  // regions escape to C++ containers. They seem to do that even now, but for
+  // mysterious reasons.
+  if (Call->isCXXCall())
+    return false;
+
+  const Decl *D = Call->getDecl();
+  if (!D)
+    return false;
+
+  ASTContext &ASTC = State->getStateManager().getContext();
+
+  // If it's one of the allocation functions we can reason about, we model
+  // its behavior explicitly.
+  if (isa<FunctionDecl>(D) && isMemFunction(cast<FunctionDecl>(D), ASTC)) {
+    return true;
+  }
+
+  // If it's not a system call, assume it frees memory.
+  SourceManager &SM = ASTC.getSourceManager();
+  if (!SM.isInSystemHeader(D->getLocation()))
+    return false;
+
+  // Process C/ObjC functions.
+  if (const FunctionDecl *FD  = dyn_cast<FunctionDecl>(D)) {
+    // White list the system functions whose arguments escape.
+    const IdentifierInfo *II = FD->getIdentifier();
+    if (!II)
+      return true;
+    StringRef FName = II->getName();
+
+    // White list thread local storage.
+    if (FName.equals("pthread_setspecific"))
+      return false;
+
+    // White list the 'XXXNoCopy' ObjC functions.
+    if (FName.endswith("NoCopy")) {
+      // Look for the deallocator argument. We know that the memory ownership
+      // is not transfered only if the deallocator argument is
+      // 'kCFAllocatorNull'.
+      for (unsigned i = 1; i < Call->getNumArgs(); ++i) {
+        const Expr *ArgE = Call->getArg(i)->IgnoreParenCasts();
+        if (const DeclRefExpr *DE = dyn_cast<DeclRefExpr>(ArgE)) {
+          StringRef DeallocatorName = DE->getFoundDecl()->getName();
+          if (DeallocatorName == "kCFAllocatorNull")
+            return true;
+        }
+      }
+      return false;
+    }
+
+    // PR12101
+    // Many CoreFoundation and CoreGraphics might allow a tracked object 
+    // to escape.
+    if (Call->isCFCGAllowingEscape(FName))
+      return false;
+
+    // Associating streams with malloced buffers. The pointer can escape if
+    // 'closefn' is specified (and if that function does free memory).
+    // Currently, we do not inspect the 'closefn' function (PR12101).
+    if (FName == "funopen")
+      if (Call->getNumArgs() >= 4 && !Call->getArgSVal(4).isConstant(0))
+        return false;
+
+    // Do not warn on pointers passed to 'setbuf' when used with std streams,
+    // these leaks might be intentional when setting the buffer for stdio.
+    // http://stackoverflow.com/questions/2671151/who-frees-setvbuf-buffer
+    if (FName == "setbuf" || FName =="setbuffer" ||
+        FName == "setlinebuf" || FName == "setvbuf") {
+      if (Call->getNumArgs() >= 1)
+        if (const DeclRefExpr *Arg =
+              dyn_cast<DeclRefExpr>(Call->getArg(0)->IgnoreParenCasts()))
+          if (const VarDecl *D = dyn_cast<VarDecl>(Arg->getDecl()))
+              if (D->getCanonicalDecl()->getName().find("std")
+                                                   != StringRef::npos)
+                return false;
+    }
+
+    // A bunch of other functions, which take ownership of a pointer (See retain
+    // release checker). Not all the parameters here are invalidated, but the
+    // Malloc checker cannot differentiate between them. The right way of doing
+    // this would be to implement a pointer escapes callback.
+    if (FName == "CVPixelBufferCreateWithBytes" ||
+        FName == "CGBitmapContextCreateWithData" ||
+        FName == "CVPixelBufferCreateWithPlanarBytes" ||
+        FName == "OSAtomicEnqueue") {
+      return false;
+    }
+
+    // Whitelist NSXXInsertXX, for example NSMapInsertIfAbsent, since they can
+    // be deallocated by NSMapRemove.
+    if (FName.startswith("NS") && (FName.find("Insert") != StringRef::npos))
+      return false;
+
+    // Otherwise, assume that the function does not free memory.
+    // Most system calls, do not free the memory.
+    return true;
+
+  // Process ObjC functions.
+  } else if (const ObjCMethodDecl * ObjCD = dyn_cast<ObjCMethodDecl>(D)) {
+    Selector S = ObjCD->getSelector();
+
+    // White list the ObjC functions which do free memory.
+    // - Anything containing 'freeWhenDone' param set to 1.
+    //   Ex: dataWithBytesNoCopy:length:freeWhenDone.
+    for (unsigned i = 1; i < S.getNumArgs(); ++i) {
+      if (S.getNameForSlot(i).equals("freeWhenDone")) {
+        if (Call->getArgSVal(i).isConstant(1))
+          return false;
+        else
+          return true;
+      }
+    }
+
+    // If the first selector ends with NoCopy, assume that the ownership is
+    // transfered as well.
+    // Ex:  [NSData dataWithBytesNoCopy:bytes length:10];
+    if (S.getNameForSlot(0).endswith("NoCopy")) {
+      return false;
+    }
+
+    // Otherwise, assume that the function does not free memory.
+    // Most system calls, do not free the memory.
+    return true;
+  }
+
+  // Otherwise, assume that the function can free memory.
+  return false;
+
+}
+
+// If the symbol we are tracking is invalidated, but not explicitly (ex: the &p
+// escapes, when we are tracking p), do not track the symbol as we cannot reason
+// about it anymore.
+ProgramStateRef
+MallocChecker::checkRegionChanges(ProgramStateRef State,
+                            const StoreManager::InvalidatedSymbols *invalidated,
+                                    ArrayRef<const MemRegion *> ExplicitRegions,
+                                    ArrayRef<const MemRegion *> Regions,
+                                    const CallOrObjCMessage *Call) const {
+  if (!invalidated || invalidated->empty())
+    return State;
+  llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols;
+
+  // If it's a call which might free or reallocate memory, we assume that all
+  // regions (explicit and implicit) escaped.
+
+  // Otherwise, whitelist explicit pointers; we still can track them.
+  if (!Call || doesNotFreeMemory(Call, State)) {
+    for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(),
+        E = ExplicitRegions.end(); I != E; ++I) {
+      if (const SymbolicRegion *R = (*I)->StripCasts()->getAs<SymbolicRegion>())
+        WhitelistedSymbols.insert(R->getSymbol());
+    }
+  }
+
+  for (StoreManager::InvalidatedSymbols::const_iterator I=invalidated->begin(),
+       E = invalidated->end(); I!=E; ++I) {
+    SymbolRef sym = *I;
+    if (WhitelistedSymbols.count(sym))
+      continue;
+    // The symbol escaped.
+    if (const RefState *RS = State->get<RegionState>(sym))
+      State = State->set<RegionState>(sym, RefState::getEscaped(RS->getStmt()));
+  }
+  return State;
+}
+
+static SymbolRef findFailedReallocSymbol(ProgramStateRef currState,
+                                         ProgramStateRef prevState) {
+  ReallocMap currMap = currState->get<ReallocPairs>();
+  ReallocMap prevMap = prevState->get<ReallocPairs>();
+
+  for (ReallocMap::iterator I = prevMap.begin(), E = prevMap.end();
+       I != E; ++I) {
+    SymbolRef sym = I.getKey();
+    if (!currMap.lookup(sym))
+      return sym;
+  }
+
+  return NULL;
+}
+
+PathDiagnosticPiece *
+MallocChecker::MallocBugVisitor::VisitNode(const ExplodedNode *N,
+                                           const ExplodedNode *PrevN,
+                                           BugReporterContext &BRC,
+                                           BugReport &BR) {
+  ProgramStateRef state = N->getState();
+  ProgramStateRef statePrev = PrevN->getState();
+
+  const RefState *RS = state->get<RegionState>(Sym);
+  const RefState *RSPrev = statePrev->get<RegionState>(Sym);
+  if (!RS && !RSPrev)
+    return 0;
+
+  const Stmt *S = 0;
+  const char *Msg = 0;
+  StackHintGeneratorForSymbol *StackHint = 0;
+
+  // Retrieve the associated statement.
+  ProgramPoint ProgLoc = N->getLocation();
+  if (isa<StmtPoint>(ProgLoc))
+    S = cast<StmtPoint>(ProgLoc).getStmt();
+  // If an assumption was made on a branch, it should be caught
+  // here by looking at the state transition.
+  if (isa<BlockEdge>(ProgLoc)) {
+    const CFGBlock *srcBlk = cast<BlockEdge>(ProgLoc).getSrc();
+    S = srcBlk->getTerminator();
+  }
+  if (!S)
+    return 0;
+
+  // Find out if this is an interesting point and what is the kind.
+  if (Mode == Normal) {
+    if (isAllocated(RS, RSPrev, S)) {
+      Msg = "Memory is allocated";
+      StackHint = new StackHintGeneratorForSymbol(Sym,
+                                                  "Returned allocated memory");
+    } else if (isReleased(RS, RSPrev, S)) {
+      Msg = "Memory is released";
+      StackHint = new StackHintGeneratorForSymbol(Sym,
+                                                  "Returned released memory");
+    } else if (isReallocFailedCheck(RS, RSPrev, S)) {
+      Mode = ReallocationFailed;
+      Msg = "Reallocation failed";
+      StackHint = new StackHintGeneratorForReallocationFailed(Sym,
+                                                       "Reallocation failed");
+
+      if (SymbolRef sym = findFailedReallocSymbol(state, statePrev)) {
+        // Is it possible to fail two reallocs WITHOUT testing in between?
+        assert((!FailedReallocSymbol || FailedReallocSymbol == sym) &&
+          "We only support one failed realloc at a time.");
+        BR.markInteresting(sym);
+        FailedReallocSymbol = sym;
+      }
+    }
+
+  // We are in a special mode if a reallocation failed later in the path.
+  } else if (Mode == ReallocationFailed) {
+    assert(FailedReallocSymbol && "No symbol to look for.");
+
+    // Is this is the first appearance of the reallocated symbol?
+    if (!statePrev->get<RegionState>(FailedReallocSymbol)) {
+      // If we ever hit this assert, that means BugReporter has decided to skip
+      // node pairs or visit them out of order.
+      assert(state->get<RegionState>(FailedReallocSymbol) &&
+        "Missed the reallocation point");
+
+      // We're at the reallocation point.
+      Msg = "Attempt to reallocate memory";
+      StackHint = new StackHintGeneratorForSymbol(Sym,
+                                                 "Returned reallocated memory");
+      FailedReallocSymbol = NULL;
+      Mode = Normal;
+    }
+  }
+
+  if (!Msg)
+    return 0;
+  assert(StackHint);
+
+  // Generate the extra diagnostic.
+  PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
+                             N->getLocationContext());
+  return new PathDiagnosticEventPiece(Pos, Msg, true, StackHint);
+}
+
+
+#define REGISTER_CHECKER(name) \
+void ento::register##name(CheckerManager &mgr) {\
+  registerCStringCheckerBasic(mgr); \
+  mgr.registerChecker<MallocChecker>()->Filter.C##name = true;\
+}
+
+REGISTER_CHECKER(MallocPessimistic)
+REGISTER_CHECKER(MallocOptimistic)
diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp
new file mode 100644
index 0000000..daec418
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp
@@ -0,0 +1,267 @@
+// MallocOverflowSecurityChecker.cpp - Check for malloc overflows -*- C++ -*-=//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This checker detects a common memory allocation security flaw.
+// Suppose 'unsigned int n' comes from an untrusted source. If the
+// code looks like 'malloc (n * 4)', and an attacker can make 'n' be
+// say MAX_UINT/4+2, then instead of allocating the correct 'n' 4-byte
+// elements, this will actually allocate only two because of overflow.
+// Then when the rest of the program attempts to store values past the
+// second element, these values will actually overwrite other items in
+// the heap, probably allowing the attacker to execute arbitrary code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/AST/EvaluatedExprVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "llvm/ADT/SmallVector.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+struct MallocOverflowCheck {
+  const BinaryOperator *mulop;
+  const Expr *variable;
+
+  MallocOverflowCheck (const BinaryOperator *m, const Expr *v) 
+    : mulop(m), variable (v)
+  {}
+};
+
+class MallocOverflowSecurityChecker : public Checker<check::ASTCodeBody> {
+public:
+  void checkASTCodeBody(const Decl *D, AnalysisManager &mgr,
+                        BugReporter &BR) const;
+
+  void CheckMallocArgument(
+    llvm::SmallVectorImpl<MallocOverflowCheck> &PossibleMallocOverflows,
+    const Expr *TheArgument, ASTContext &Context) const;
+
+  void OutputPossibleOverflows(
+    llvm::SmallVectorImpl<MallocOverflowCheck> &PossibleMallocOverflows,
+    const Decl *D, BugReporter &BR, AnalysisManager &mgr) const;
+
+};
+} // end anonymous namespace
+
+void MallocOverflowSecurityChecker::CheckMallocArgument(
+  llvm::SmallVectorImpl<MallocOverflowCheck> &PossibleMallocOverflows,
+  const Expr *TheArgument,
+  ASTContext &Context) const {
+
+  /* Look for a linear combination with a single variable, and at least
+   one multiplication.
+   Reject anything that applies to the variable: an explicit cast,
+   conditional expression, an operation that could reduce the range
+   of the result, or anything too complicated :-).  */
+  const Expr * e = TheArgument;
+  const BinaryOperator * mulop = NULL;
+
+  for (;;) {
+    e = e->IgnoreParenImpCasts();
+    if (isa<BinaryOperator>(e)) {
+      const BinaryOperator * binop = dyn_cast<BinaryOperator>(e);
+      BinaryOperatorKind opc = binop->getOpcode();
+      // TODO: ignore multiplications by 1, reject if multiplied by 0.
+      if (mulop == NULL && opc == BO_Mul)
+        mulop = binop;
+      if (opc != BO_Mul && opc != BO_Add && opc != BO_Sub && opc != BO_Shl)
+        return;
+
+      const Expr *lhs = binop->getLHS();
+      const Expr *rhs = binop->getRHS();
+      if (rhs->isEvaluatable(Context))
+        e = lhs;
+      else if ((opc == BO_Add || opc == BO_Mul)
+               && lhs->isEvaluatable(Context))
+        e = rhs;
+      else
+        return;
+    }
+    else if (isa<DeclRefExpr>(e) || isa<MemberExpr>(e))
+      break;
+    else
+      return;
+  }
+
+  if (mulop == NULL)
+    return;
+
+  //  We've found the right structure of malloc argument, now save
+  // the data so when the body of the function is completely available
+  // we can check for comparisons.
+
+  // TODO: Could push this into the innermost scope where 'e' is
+  // defined, rather than the whole function.
+  PossibleMallocOverflows.push_back(MallocOverflowCheck(mulop, e));
+}
+
+namespace {
+// A worker class for OutputPossibleOverflows.
+class CheckOverflowOps :
+  public EvaluatedExprVisitor<CheckOverflowOps> {
+public:
+  typedef llvm::SmallVectorImpl<MallocOverflowCheck> theVecType;
+
+private:
+    theVecType &toScanFor;
+    ASTContext &Context;
+
+    bool isIntZeroExpr(const Expr *E) const {
+      if (!E->getType()->isIntegralOrEnumerationType())
+        return false;
+      llvm::APSInt Result;
+      if (E->EvaluateAsInt(Result, Context))
+        return Result == 0;
+      return false;
+    }
+
+    void CheckExpr(const Expr *E_p) {
+      const Expr *E = E_p->IgnoreParenImpCasts();
+
+      theVecType::iterator i = toScanFor.end();
+      theVecType::iterator e = toScanFor.begin();
+
+      if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) {
+        const Decl * EdreD = DR->getDecl();
+        while (i != e) {
+          --i;
+          if (const DeclRefExpr *DR_i = dyn_cast<DeclRefExpr>(i->variable)) {
+            if (DR_i->getDecl() == EdreD)
+              i = toScanFor.erase(i);
+          }
+        }
+      }
+      else if (isa<MemberExpr>(E)) {
+        // No points-to analysis, just look at the member
+        const Decl * EmeMD = dyn_cast<MemberExpr>(E)->getMemberDecl();
+        while (i != e) {
+          --i;
+          if (isa<MemberExpr>(i->variable)) {
+            if (dyn_cast<MemberExpr>(i->variable)->getMemberDecl() == EmeMD)
+              i = toScanFor.erase (i);
+          }
+        }
+      }
+    }
+
+  public:
+    void VisitBinaryOperator(BinaryOperator *E) {
+      if (E->isComparisonOp()) {
+        const Expr * lhs = E->getLHS();
+        const Expr * rhs = E->getRHS();
+        // Ignore comparisons against zero, since they generally don't
+        // protect against an overflow.
+        if (!isIntZeroExpr(lhs) && ! isIntZeroExpr(rhs)) {
+          CheckExpr(lhs);
+          CheckExpr(rhs);
+        }
+      }
+      EvaluatedExprVisitor<CheckOverflowOps>::VisitBinaryOperator(E);
+    }
+
+    /* We specifically ignore loop conditions, because they're typically
+     not error checks.  */
+    void VisitWhileStmt(WhileStmt *S) {
+      return this->Visit(S->getBody());
+    }
+    void VisitForStmt(ForStmt *S) {
+      return this->Visit(S->getBody());
+    }
+    void VisitDoStmt(DoStmt *S) {
+      return this->Visit(S->getBody());
+    }
+
+    CheckOverflowOps(theVecType &v, ASTContext &ctx)
+    : EvaluatedExprVisitor<CheckOverflowOps>(ctx),
+      toScanFor(v), Context(ctx)
+    { }
+  };
+}
+
+// OutputPossibleOverflows - We've found a possible overflow earlier,
+// now check whether Body might contain a comparison which might be
+// preventing the overflow.
+// This doesn't do flow analysis, range analysis, or points-to analysis; it's
+// just a dumb "is there a comparison" scan.  The aim here is to
+// detect the most blatent cases of overflow and educate the
+// programmer.
+void MallocOverflowSecurityChecker::OutputPossibleOverflows(
+  llvm::SmallVectorImpl<MallocOverflowCheck> &PossibleMallocOverflows,
+  const Decl *D, BugReporter &BR, AnalysisManager &mgr) const {
+  // By far the most common case: nothing to check.
+  if (PossibleMallocOverflows.empty())
+    return;
+
+  // Delete any possible overflows which have a comparison.
+  CheckOverflowOps c(PossibleMallocOverflows, BR.getContext());
+  c.Visit(mgr.getAnalysisDeclContext(D)->getBody());
+
+  // Output warnings for all overflows that are left.
+  for (CheckOverflowOps::theVecType::iterator
+       i = PossibleMallocOverflows.begin(),
+       e = PossibleMallocOverflows.end();
+       i != e;
+       ++i) {
+    SourceRange R = i->mulop->getSourceRange();
+    BR.EmitBasicReport(D, "malloc() size overflow", categories::UnixAPI,
+      "the computation of the size of the memory allocation may overflow",
+      PathDiagnosticLocation::createOperatorLoc(i->mulop,
+                                                BR.getSourceManager()), &R, 1);
+  }
+}
+
+void MallocOverflowSecurityChecker::checkASTCodeBody(const Decl *D,
+                                             AnalysisManager &mgr,
+                                             BugReporter &BR) const {
+
+  CFG *cfg = mgr.getCFG(D);
+  if (!cfg)
+    return;
+
+  // A list of variables referenced in possibly overflowing malloc operands.
+  llvm::SmallVector<MallocOverflowCheck, 2> PossibleMallocOverflows;
+
+  for (CFG::iterator it = cfg->begin(), ei = cfg->end(); it != ei; ++it) {
+    CFGBlock *block = *it;
+    for (CFGBlock::iterator bi = block->begin(), be = block->end();
+         bi != be; ++bi) {
+      if (const CFGStmt *CS = bi->getAs<CFGStmt>()) {
+        if (const CallExpr *TheCall = dyn_cast<CallExpr>(CS->getStmt())) {
+          // Get the callee.
+          const FunctionDecl *FD = TheCall->getDirectCallee();
+
+          if (!FD)
+            return;
+
+          // Get the name of the callee. If it's a builtin, strip off the prefix.
+          IdentifierInfo *FnInfo = FD->getIdentifier();
+          if (!FnInfo)
+            return;
+
+          if (FnInfo->isStr ("malloc") || FnInfo->isStr ("_MALLOC")) {
+            if (TheCall->getNumArgs() == 1)
+              CheckMallocArgument(PossibleMallocOverflows, TheCall->getArg(0),
+                                  mgr.getASTContext());
+          }
+        }
+      }
+    }
+  }
+
+  OutputPossibleOverflows(PossibleMallocOverflows, D, BR, mgr);
+}
+
+void ento::registerMallocOverflowSecurityChecker(CheckerManager &mgr) {
+  mgr.registerChecker<MallocOverflowSecurityChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp
new file mode 100644
index 0000000..08a9da1
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp
@@ -0,0 +1,211 @@
+// MallocSizeofChecker.cpp - Check for dubious malloc arguments ---*- C++ -*-=//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Reports inconsistencies between the casted type of the return value of a
+// malloc/calloc/realloc call and the operand of any sizeof expressions
+// contained within its argument(s).
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/TypeLoc.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+typedef std::pair<const TypeSourceInfo *, const CallExpr *> TypeCallPair;
+typedef llvm::PointerUnion<const Stmt *, const VarDecl *> ExprParent;
+
+class CastedAllocFinder
+  : public ConstStmtVisitor<CastedAllocFinder, TypeCallPair> {
+  IdentifierInfo *II_malloc, *II_calloc, *II_realloc;
+
+public:
+  struct CallRecord {
+    ExprParent CastedExprParent;
+    const Expr *CastedExpr;
+    const TypeSourceInfo *ExplicitCastType;
+    const CallExpr *AllocCall;
+
+    CallRecord(ExprParent CastedExprParent, const Expr *CastedExpr,
+               const TypeSourceInfo *ExplicitCastType,
+               const CallExpr *AllocCall)
+      : CastedExprParent(CastedExprParent), CastedExpr(CastedExpr),
+        ExplicitCastType(ExplicitCastType), AllocCall(AllocCall) {}
+  };
+
+  typedef std::vector<CallRecord> CallVec;
+  CallVec Calls;
+
+  CastedAllocFinder(ASTContext *Ctx) :
+    II_malloc(&Ctx->Idents.get("malloc")),
+    II_calloc(&Ctx->Idents.get("calloc")),
+    II_realloc(&Ctx->Idents.get("realloc")) {}
+
+  void VisitChild(ExprParent Parent, const Stmt *S) {
+    TypeCallPair AllocCall = Visit(S);
+    if (AllocCall.second && AllocCall.second != S)
+      Calls.push_back(CallRecord(Parent, cast<Expr>(S), AllocCall.first,
+                                 AllocCall.second));
+  }
+
+  void VisitChildren(const Stmt *S) {
+    for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
+         I!=E; ++I)
+      if (const Stmt *child = *I)
+        VisitChild(S, child);
+  }
+
+  TypeCallPair VisitCastExpr(const CastExpr *E) {
+    return Visit(E->getSubExpr());
+  }
+
+  TypeCallPair VisitExplicitCastExpr(const ExplicitCastExpr *E) {
+    return TypeCallPair(E->getTypeInfoAsWritten(),
+                        Visit(E->getSubExpr()).second);
+  }
+
+  TypeCallPair VisitParenExpr(const ParenExpr *E) {
+    return Visit(E->getSubExpr());
+  }
+
+  TypeCallPair VisitStmt(const Stmt *S) {
+    VisitChildren(S);
+    return TypeCallPair();
+  }
+
+  TypeCallPair VisitCallExpr(const CallExpr *E) {
+    VisitChildren(E);
+    const FunctionDecl *FD = E->getDirectCallee();
+    if (FD) {
+      IdentifierInfo *II = FD->getIdentifier();
+      if (II == II_malloc || II == II_calloc || II == II_realloc)
+        return TypeCallPair((const TypeSourceInfo *)0, E);
+    }
+    return TypeCallPair();
+  }
+
+  TypeCallPair VisitDeclStmt(const DeclStmt *S) {
+    for (DeclStmt::const_decl_iterator I = S->decl_begin(), E = S->decl_end();
+         I!=E; ++I)
+      if (const VarDecl *VD = dyn_cast<VarDecl>(*I))
+        if (const Expr *Init = VD->getInit())
+          VisitChild(VD, Init);
+    return TypeCallPair();
+  }
+};
+
+class SizeofFinder : public ConstStmtVisitor<SizeofFinder> {
+public:
+  std::vector<const UnaryExprOrTypeTraitExpr *> Sizeofs;
+
+  void VisitBinMul(const BinaryOperator *E) {
+    Visit(E->getLHS());
+    Visit(E->getRHS());
+  }
+
+  void VisitBinAdd(const BinaryOperator *E) {
+    Visit(E->getLHS());
+    Visit(E->getRHS());
+  }
+
+  void VisitImplicitCastExpr(const ImplicitCastExpr *E) {
+    return Visit(E->getSubExpr());
+  }
+
+  void VisitParenExpr(const ParenExpr *E) {
+    return Visit(E->getSubExpr());
+  }
+
+  void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E) {
+    if (E->getKind() != UETT_SizeOf)
+      return;
+
+    Sizeofs.push_back(E);
+  }
+};
+
+class MallocSizeofChecker : public Checker<check::ASTCodeBody> {
+public:
+  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
+                        BugReporter &BR) const {
+    AnalysisDeclContext *ADC = mgr.getAnalysisDeclContext(D);
+    CastedAllocFinder Finder(&BR.getContext());
+    Finder.Visit(D->getBody());
+    for (CastedAllocFinder::CallVec::iterator i = Finder.Calls.begin(),
+         e = Finder.Calls.end(); i != e; ++i) {
+      QualType CastedType = i->CastedExpr->getType();
+      if (!CastedType->isPointerType())
+        continue;
+      QualType PointeeType = CastedType->getAs<PointerType>()->getPointeeType();
+      if (PointeeType->isVoidType())
+        continue;
+
+      for (CallExpr::const_arg_iterator ai = i->AllocCall->arg_begin(),
+           ae = i->AllocCall->arg_end(); ai != ae; ++ai) {
+        if (!(*ai)->getType()->isIntegerType())
+          continue;
+
+        SizeofFinder SFinder;
+        SFinder.Visit(*ai);
+        if (SFinder.Sizeofs.size() != 1)
+          continue;
+
+        QualType SizeofType = SFinder.Sizeofs[0]->getTypeOfArgument();
+        if (!BR.getContext().hasSameUnqualifiedType(PointeeType, SizeofType)) {
+          const TypeSourceInfo *TSI = 0;
+          if (i->CastedExprParent.is<const VarDecl *>()) {
+            TSI =
+              i->CastedExprParent.get<const VarDecl *>()->getTypeSourceInfo();
+          } else {
+            TSI = i->ExplicitCastType;
+          }
+
+          SmallString<64> buf;
+          llvm::raw_svector_ostream OS(buf);
+
+          OS << "Result of '"
+             << i->AllocCall->getDirectCallee()->getIdentifier()->getName()
+             << "' is converted to type '"
+             << CastedType.getAsString() << "', whose pointee type '"
+             << PointeeType.getAsString() << "' is incompatible with "
+             << "sizeof operand type '" << SizeofType.getAsString() << "'";
+          llvm::SmallVector<SourceRange, 4> Ranges;
+          Ranges.push_back(i->AllocCall->getCallee()->getSourceRange());
+          Ranges.push_back(SFinder.Sizeofs[0]->getSourceRange());
+          if (TSI)
+            Ranges.push_back(TSI->getTypeLoc().getSourceRange());
+
+          PathDiagnosticLocation L =
+            PathDiagnosticLocation::createBegin(i->AllocCall->getCallee(),
+                                                BR.getSourceManager(), ADC);
+
+          BR.EmitBasicReport(D, "allocator sizeof operand mismatch",
+                             categories::UnixAPI,
+                             OS.str(),
+                             L, Ranges.data(), Ranges.size());
+        }
+      }
+    }
+  }
+};
+
+}
+
+void ento::registerMallocSizeofChecker(CheckerManager &mgr) {
+  mgr.registerChecker<MallocSizeofChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
new file mode 100644
index 0000000..4989ba8
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
@@ -0,0 +1,89 @@
+//=- 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 its 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 "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Decl.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class NSAutoreleasePoolChecker
+  : public Checker<check::PreObjCMessage> {
+  mutable OwningPtr<BugType> BT;
+  mutable Selector releaseS;
+
+public:
+  void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const;    
+};
+
+} // end anonymous namespace
+
+void NSAutoreleasePoolChecker::checkPreObjCMessage(ObjCMessage msg,
+                                                   CheckerContext &C) const {
+  
+  const Expr *receiver = msg.getInstanceReceiver();
+  if (!receiver)
+    return;
+  
+  // FIXME: Enhance with value-tracking information instead of consulting
+  // the type of the expression.
+  const ObjCObjectPointerType* PT =
+    receiver->getType()->getAs<ObjCObjectPointerType>();
+  
+  if (!PT)
+    return;  
+  const ObjCInterfaceDecl *OD = PT->getInterfaceDecl();
+  if (!OD)
+    return;  
+  if (!OD->getIdentifier()->getName().equals("NSAutoreleasePool"))
+    return;
+
+  if (releaseS.isNull())
+    releaseS = GetNullarySelector("release", C.getASTContext());
+  // Sending 'release' message?
+  if (msg.getSelector() != releaseS)
+    return;
+
+  if (!BT)
+    BT.reset(new BugType("Use -drain instead of -release",
+                         "API Upgrade (Apple)"));
+
+  ExplodedNode *N = C.addTransition();
+  if (!N) {
+    assert(0);
+    return;
+  }
+
+  BugReport *Report = new BugReport(*BT, "Use -drain instead of -release when "
+    "using NSAutoreleasePool and garbage collection", N);
+  Report->addRange(msg.getSourceRange());
+  C.EmitReport(Report);
+}
+
+void ento::registerNSAutoreleasePoolChecker(CheckerManager &mgr) {
+  if (mgr.getLangOpts().getGC() != LangOptions::NonGC)
+    mgr.registerChecker<NSAutoreleasePoolChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
new file mode 100644
index 0000000..f826573
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
@@ -0,0 +1,334 @@
+//=- NSErrorChecker.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 "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Decl.h"
+#include "llvm/ADT/SmallVector.h"
+
+using namespace clang;
+using namespace ento;
+
+static bool IsNSError(QualType T, IdentifierInfo *II);
+static bool IsCFError(QualType T, IdentifierInfo *II);
+
+//===----------------------------------------------------------------------===//
+// NSErrorMethodChecker
+//===----------------------------------------------------------------------===//
+
+namespace {
+class NSErrorMethodChecker
+    : public Checker< check::ASTDecl<ObjCMethodDecl> > {
+  mutable IdentifierInfo *II;
+
+public:
+  NSErrorMethodChecker() : II(0) { }
+
+  void checkASTDecl(const ObjCMethodDecl *D,
+                    AnalysisManager &mgr, BugReporter &BR) const;
+};
+}
+
+void NSErrorMethodChecker::checkASTDecl(const ObjCMethodDecl *D,
+                                        AnalysisManager &mgr,
+                                        BugReporter &BR) const {
+  if (!D->isThisDeclarationADefinition())
+    return;
+  if (!D->getResultType()->isVoidType())
+    return;
+
+  if (!II)
+    II = &D->getASTContext().Idents.get("NSError"); 
+
+  bool hasNSError = false;
+  for (ObjCMethodDecl::param_const_iterator
+         I = D->param_begin(), E = D->param_end(); I != E; ++I)  {
+    if (IsNSError((*I)->getType(), II)) {
+      hasNSError = true;
+      break;
+    }
+  }
+
+  if (hasNSError) {
+    const char *err = "Method accepting NSError** "
+        "should have a non-void return value to indicate whether or not an "
+        "error occurred";
+    PathDiagnosticLocation L =
+      PathDiagnosticLocation::create(D, BR.getSourceManager());
+    BR.EmitBasicReport(D, "Bad return type when passing NSError**",
+                       "Coding conventions (Apple)", err, L);
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// CFErrorFunctionChecker
+//===----------------------------------------------------------------------===//
+
+namespace {
+class CFErrorFunctionChecker
+    : public Checker< check::ASTDecl<FunctionDecl> > {
+  mutable IdentifierInfo *II;
+
+public:
+  CFErrorFunctionChecker() : II(0) { }
+
+  void checkASTDecl(const FunctionDecl *D,
+                    AnalysisManager &mgr, BugReporter &BR) const;
+};
+}
+
+void CFErrorFunctionChecker::checkASTDecl(const FunctionDecl *D,
+                                        AnalysisManager &mgr,
+                                        BugReporter &BR) const {
+  if (!D->doesThisDeclarationHaveABody())
+    return;
+  if (!D->getResultType()->isVoidType())
+    return;
+
+  if (!II)
+    II = &D->getASTContext().Idents.get("CFErrorRef"); 
+
+  bool hasCFError = false;
+  for (FunctionDecl::param_const_iterator
+         I = D->param_begin(), E = D->param_end(); I != E; ++I)  {
+    if (IsCFError((*I)->getType(), II)) {
+      hasCFError = true;
+      break;
+    }
+  }
+
+  if (hasCFError) {
+    const char *err = "Function accepting CFErrorRef* "
+        "should have a non-void return value to indicate whether or not an "
+        "error occurred";
+    PathDiagnosticLocation L =
+      PathDiagnosticLocation::create(D, BR.getSourceManager());
+    BR.EmitBasicReport(D, "Bad return type when passing CFErrorRef*",
+                       "Coding conventions (Apple)", err, L);
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// NSOrCFErrorDerefChecker
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+class NSErrorDerefBug : public BugType {
+public:
+  NSErrorDerefBug() : BugType("NSError** null dereference",
+                              "Coding conventions (Apple)") {}
+};
+
+class CFErrorDerefBug : public BugType {
+public:
+  CFErrorDerefBug() : BugType("CFErrorRef* null dereference",
+                              "Coding conventions (Apple)") {}
+};
+
+}
+
+namespace {
+class NSOrCFErrorDerefChecker
+    : public Checker< check::Location,
+                        check::Event<ImplicitNullDerefEvent> > {
+  mutable IdentifierInfo *NSErrorII, *CFErrorII;
+public:
+  bool ShouldCheckNSError, ShouldCheckCFError;
+  NSOrCFErrorDerefChecker() : NSErrorII(0), CFErrorII(0),
+                              ShouldCheckNSError(0), ShouldCheckCFError(0) { }
+
+  void checkLocation(SVal loc, bool isLoad, const Stmt *S,
+                     CheckerContext &C) const;
+  void checkEvent(ImplicitNullDerefEvent event) const;
+};
+}
+
+namespace { struct NSErrorOut {}; }
+namespace { struct CFErrorOut {}; }
+
+typedef llvm::ImmutableMap<SymbolRef, unsigned> ErrorOutFlag;
+
+namespace clang {
+namespace ento {
+  template <>
+  struct ProgramStateTrait<NSErrorOut> : public ProgramStatePartialTrait<ErrorOutFlag> {  
+    static void *GDMIndex() { static int index = 0; return &index; }
+  };
+  template <>
+  struct ProgramStateTrait<CFErrorOut> : public ProgramStatePartialTrait<ErrorOutFlag> {  
+    static void *GDMIndex() { static int index = 0; return &index; }
+  };
+}
+}
+
+template <typename T>
+static bool hasFlag(SVal val, ProgramStateRef state) {
+  if (SymbolRef sym = val.getAsSymbol())
+    if (const unsigned *attachedFlags = state->get<T>(sym))
+      return *attachedFlags;
+  return false;
+}
+
+template <typename T>
+static void setFlag(ProgramStateRef state, SVal val, CheckerContext &C) {
+  // We tag the symbol that the SVal wraps.
+  if (SymbolRef sym = val.getAsSymbol())
+    C.addTransition(state->set<T>(sym, true));
+}
+
+static QualType parameterTypeFromSVal(SVal val, CheckerContext &C) {
+  const StackFrameContext *
+    SFC = C.getLocationContext()->getCurrentStackFrame();
+  if (const loc::MemRegionVal* X = dyn_cast<loc::MemRegionVal>(&val)) {
+    const MemRegion* R = X->getRegion();
+    if (const VarRegion *VR = R->getAs<VarRegion>())
+      if (const StackArgumentsSpaceRegion *
+          stackReg = dyn_cast<StackArgumentsSpaceRegion>(VR->getMemorySpace()))
+        if (stackReg->getStackFrame() == SFC)
+          return VR->getValueType();
+  }
+
+  return QualType();
+}
+
+void NSOrCFErrorDerefChecker::checkLocation(SVal loc, bool isLoad,
+                                            const Stmt *S,
+                                            CheckerContext &C) const {
+  if (!isLoad)
+    return;
+  if (loc.isUndef() || !isa<Loc>(loc))
+    return;
+
+  ASTContext &Ctx = C.getASTContext();
+  ProgramStateRef state = C.getState();
+
+  // If we are loading from NSError**/CFErrorRef* parameter, mark the resulting
+  // SVal so that we can later check it when handling the
+  // ImplicitNullDerefEvent event.
+  // FIXME: Cumbersome! Maybe add hook at construction of SVals at start of
+  // function ?
+
+  QualType parmT = parameterTypeFromSVal(loc, C);
+  if (parmT.isNull())
+    return;
+
+  if (!NSErrorII)
+    NSErrorII = &Ctx.Idents.get("NSError");
+  if (!CFErrorII)
+    CFErrorII = &Ctx.Idents.get("CFErrorRef");
+
+  if (ShouldCheckNSError && IsNSError(parmT, NSErrorII)) {
+    setFlag<NSErrorOut>(state, state->getSVal(cast<Loc>(loc)), C);
+    return;
+  }
+
+  if (ShouldCheckCFError && IsCFError(parmT, CFErrorII)) {
+    setFlag<CFErrorOut>(state, state->getSVal(cast<Loc>(loc)), C);
+    return;
+  }
+}
+
+void NSOrCFErrorDerefChecker::checkEvent(ImplicitNullDerefEvent event) const {
+  if (event.IsLoad)
+    return;
+
+  SVal loc = event.Location;
+  ProgramStateRef state = event.SinkNode->getState();
+  BugReporter &BR = *event.BR;
+
+  bool isNSError = hasFlag<NSErrorOut>(loc, state);
+  bool isCFError = false;
+  if (!isNSError)
+    isCFError = hasFlag<CFErrorOut>(loc, state);
+
+  if (!(isNSError || isCFError))
+    return;
+
+  // Storing to possible null NSError/CFErrorRef out parameter.
+
+  // Emit an error.
+  std::string err;
+  llvm::raw_string_ostream os(err);
+    os << "Potential null dereference.  According to coding standards ";
+
+  if (isNSError)
+    os << "in 'Creating and Returning NSError Objects' the parameter '";
+  else
+    os << "documented in CoreFoundation/CFError.h the parameter '";
+
+  os  << "' may be null.";
+
+  BugType *bug = 0;
+  if (isNSError)
+    bug = new NSErrorDerefBug();
+  else
+    bug = new CFErrorDerefBug();
+  BugReport *report = new BugReport(*bug, os.str(),
+                                                    event.SinkNode);
+  BR.EmitReport(report);
+}
+
+static bool IsNSError(QualType T, IdentifierInfo *II) {
+
+  const PointerType* PPT = T->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;
+}
+
+static bool IsCFError(QualType T, IdentifierInfo *II) {
+  const PointerType* PPT = T->getAs<PointerType>();
+  if (!PPT) return false;
+
+  const TypedefType* TT = PPT->getPointeeType()->getAs<TypedefType>();
+  if (!TT) return false;
+
+  return TT->getDecl()->getIdentifier() == II;
+}
+
+void ento::registerNSErrorChecker(CheckerManager &mgr) {
+  mgr.registerChecker<NSErrorMethodChecker>();
+  NSOrCFErrorDerefChecker *
+    checker = mgr.registerChecker<NSOrCFErrorDerefChecker>();
+  checker->ShouldCheckNSError = true;
+}
+
+void ento::registerCFErrorChecker(CheckerManager &mgr) {
+  mgr.registerChecker<CFErrorFunctionChecker>();
+  NSOrCFErrorDerefChecker *
+    checker = mgr.registerChecker<NSOrCFErrorDerefChecker>();
+  checker->ShouldCheckCFError = true;
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
new file mode 100644
index 0000000..c2d7c09
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
@@ -0,0 +1,146 @@
+//=== NoReturnFunctionChecker.cpp -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines NoReturnFunctionChecker, which evaluates functions that do not
+// return to the caller.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
+#include "llvm/ADT/StringSwitch.h"
+#include <cstdarg>
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class NoReturnFunctionChecker : public Checker< check::PostStmt<CallExpr>,
+                                                check::PostObjCMessage > {
+public:
+  void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
+  void checkPostObjCMessage(const ObjCMessage &msg, CheckerContext &C) const;
+};
+
+}
+
+void NoReturnFunctionChecker::checkPostStmt(const CallExpr *CE,
+                                            CheckerContext &C) const {
+  ProgramStateRef state = C.getState();
+  const Expr *Callee = CE->getCallee();
+
+  bool BuildSinks = getFunctionExtInfo(Callee->getType()).getNoReturn();
+
+  if (!BuildSinks) {
+    SVal L = state->getSVal(Callee, C.getLocationContext());
+    const FunctionDecl *FD = L.getAsFunctionDecl();
+    if (!FD)
+      return;
+
+    if (FD->getAttr<AnalyzerNoReturnAttr>())
+      BuildSinks = true;
+    else if (const IdentifierInfo *II = FD->getIdentifier()) {
+      // 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.
+      BuildSinks
+        = llvm::StringSwitch<bool>(StringRef(II->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)
+    C.generateSink();
+}
+
+static bool END_WITH_NULL isMultiArgSelector(const Selector *Sel, ...) {
+  va_list argp;
+  va_start(argp, Sel);
+
+  unsigned Slot = 0;
+  const char *Arg;
+  while ((Arg = va_arg(argp, const char *))) {
+    if (!Sel->getNameForSlot(Slot).equals(Arg))
+      break; // still need to va_end!
+    ++Slot;
+  }
+
+  va_end(argp);
+
+  // We only succeeded if we made it to the end of the argument list.
+  return (Arg == NULL);
+}
+
+void NoReturnFunctionChecker::checkPostObjCMessage(const ObjCMessage &Msg,
+                                                   CheckerContext &C) const {
+  // HACK: This entire check is to handle two messages in the Cocoa frameworks:
+  // -[NSAssertionHandler
+  //    handleFailureInMethod:object:file:lineNumber:description:]
+  // -[NSAssertionHandler
+  //    handleFailureInFunction:file:lineNumber:description:]
+  // Eventually these should be annotated with __attribute__((noreturn)).
+  // Because ObjC messages use dynamic dispatch, it is not generally safe to
+  // assume certain methods can't return. In cases where it is definitely valid,
+  // see if you can mark the methods noreturn or analyzer_noreturn instead of
+  // adding more explicit checks to this method.
+
+  if (!Msg.isInstanceMessage())
+    return;
+
+  const ObjCInterfaceDecl *Receiver = Msg.getReceiverInterface();
+  if (!Receiver)
+    return;
+  if (!Receiver->getIdentifier()->isStr("NSAssertionHandler"))
+    return;
+
+  Selector Sel = Msg.getSelector();
+  switch (Sel.getNumArgs()) {
+  default:
+    return;
+  case 4:
+    if (!isMultiArgSelector(&Sel, "handleFailureInFunction", "file",
+                            "lineNumber", "description", NULL))
+      return;
+    break;
+  case 5:
+    if (!isMultiArgSelector(&Sel, "handleFailureInMethod", "object", "file",
+                            "lineNumber", "description", NULL))
+      return;
+    break;
+  }
+
+  // If we got here, it's one of the messages we care about.
+  C.generateSink();
+}
+
+
+void ento::registerNoReturnFunctionChecker(CheckerManager &mgr) {
+  mgr.registerChecker<NoReturnFunctionChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp
new file mode 100644
index 0000000..7b724d2
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp
@@ -0,0 +1,218 @@
+//=== OSAtomicChecker.cpp - OSAtomic functions evaluator --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This checker evaluates OSAtomic functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/Basic/Builtins.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class OSAtomicChecker : public Checker<eval::InlineCall> {
+public:
+  bool inlineCall(const CallExpr *CE, ExprEngine &Eng,
+                  ExplodedNode *Pred, ExplodedNodeSet &Dst) const;
+
+private:
+  bool evalOSAtomicCompareAndSwap(const CallExpr *CE,
+                                  ExprEngine &Eng,
+                                  ExplodedNode *Pred,
+                                  ExplodedNodeSet &Dst) const;
+};
+}
+
+static StringRef getCalleeName(ProgramStateRef State,
+                               const CallExpr *CE,
+                               const LocationContext *LCtx) {
+  const Expr *Callee = CE->getCallee();
+  SVal L = State->getSVal(Callee, LCtx);
+  const FunctionDecl *funDecl =  L.getAsFunctionDecl();
+  if (!funDecl)
+    return StringRef();
+  IdentifierInfo *funI = funDecl->getIdentifier();
+  if (!funI)
+    return StringRef();
+  return funI->getName();
+}
+
+bool OSAtomicChecker::inlineCall(const CallExpr *CE,
+                                 ExprEngine &Eng,
+                                 ExplodedNode *Pred,
+                                 ExplodedNodeSet &Dst) const {
+  StringRef FName = getCalleeName(Pred->getState(),
+                                  CE, Pred->getLocationContext());
+  if (FName.empty())
+    return false;
+
+  // Check for compare and swap.
+  if (FName.startswith("OSAtomicCompareAndSwap") ||
+      FName.startswith("objc_atomicCompareAndSwap"))
+    return evalOSAtomicCompareAndSwap(CE, Eng, Pred, Dst);
+
+  // FIXME: Other atomics.
+  return false;
+}
+
+bool OSAtomicChecker::evalOSAtomicCompareAndSwap(const CallExpr *CE,
+                                                 ExprEngine &Eng,
+                                                 ExplodedNode *Pred,
+                                                 ExplodedNodeSet &Dst) const {
+  // Not enough arguments to match OSAtomicCompareAndSwap?
+  if (CE->getNumArgs() != 3)
+    return false;
+
+  ASTContext &Ctx = Eng.getContext();
+  const Expr *oldValueExpr = CE->getArg(0);
+  QualType oldValueType = Ctx.getCanonicalType(oldValueExpr->getType());
+
+  const Expr *newValueExpr = CE->getArg(1);
+  QualType newValueType = Ctx.getCanonicalType(newValueExpr->getType());
+
+  // Do the types of 'oldValue' and 'newValue' match?
+  if (oldValueType != newValueType)
+    return false;
+
+  const Expr *theValueExpr = CE->getArg(2);
+  const PointerType *theValueType=theValueExpr->getType()->getAs<PointerType>();
+
+  // theValueType not a pointer?
+  if (!theValueType)
+    return false;
+
+  QualType theValueTypePointee =
+    Ctx.getCanonicalType(theValueType->getPointeeType()).getUnqualifiedType();
+
+  // The pointee must match newValueType and oldValueType.
+  if (theValueTypePointee != newValueType)
+    return false;
+
+  static SimpleProgramPointTag OSAtomicLoadTag("OSAtomicChecker : Load");
+  static SimpleProgramPointTag OSAtomicStoreTag("OSAtomicChecker : Store");
+  
+  // Load 'theValue'.
+  ProgramStateRef state = Pred->getState();
+  const LocationContext *LCtx = Pred->getLocationContext();
+  ExplodedNodeSet Tmp;
+  SVal location = state->getSVal(theValueExpr, LCtx);
+  // Here we should use the value type of the region as the load type, because
+  // we are simulating the semantics of the function, not the semantics of 
+  // passing argument. So the type of theValue expr is not we are loading.
+  // But usually the type of the varregion is not the type we want either,
+  // we still need to do a CastRetrievedVal in store manager. So actually this
+  // LoadTy specifying can be omitted. But we put it here to emphasize the 
+  // semantics.
+  QualType LoadTy;
+  if (const TypedValueRegion *TR =
+      dyn_cast_or_null<TypedValueRegion>(location.getAsRegion())) {
+    LoadTy = TR->getValueType();
+  }
+  Eng.evalLoad(Tmp, CE, theValueExpr, Pred,
+               state, location, &OSAtomicLoadTag, LoadTy);
+
+  if (Tmp.empty()) {
+    // If no nodes were generated, other checkers must have generated sinks. 
+    // We return an empty Dst.
+    return true;
+  }
+ 
+  for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end();
+       I != E; ++I) {
+
+    ExplodedNode *N = *I;
+    ProgramStateRef stateLoad = N->getState();
+
+    // Use direct bindings from the environment since we are forcing a load
+    // from a location that the Environment would typically not be used
+    // to bind a value.
+    SVal theValueVal_untested = stateLoad->getSVal(theValueExpr, LCtx, true);
+
+    SVal oldValueVal_untested = stateLoad->getSVal(oldValueExpr, LCtx);
+
+    // FIXME: Issue an error.
+    if (theValueVal_untested.isUndef() || oldValueVal_untested.isUndef()) {
+      return false;
+    }
+    
+    DefinedOrUnknownSVal theValueVal =
+      cast<DefinedOrUnknownSVal>(theValueVal_untested);
+    DefinedOrUnknownSVal oldValueVal =
+      cast<DefinedOrUnknownSVal>(oldValueVal_untested);
+
+    SValBuilder &svalBuilder = Eng.getSValBuilder();
+
+    // Perform the comparison.
+    DefinedOrUnknownSVal Cmp =
+      svalBuilder.evalEQ(stateLoad,theValueVal,oldValueVal);
+
+    ProgramStateRef stateEqual = stateLoad->assume(Cmp, true);
+
+    // Were they equal?
+    if (stateEqual) {
+      // Perform the store.
+      ExplodedNodeSet TmpStore;
+      SVal val = stateEqual->getSVal(newValueExpr, LCtx);
+
+      // Handle implicit value casts.
+      if (const TypedValueRegion *R =
+          dyn_cast_or_null<TypedValueRegion>(location.getAsRegion())) {
+        val = svalBuilder.evalCast(val,R->getValueType(), newValueExpr->getType());
+      }
+
+      Eng.evalStore(TmpStore, CE, theValueExpr, N,
+                    stateEqual, location, val, &OSAtomicStoreTag);
+
+      if (TmpStore.empty()) {
+        // If no nodes were generated, other checkers must have generated sinks. 
+        // We return an empty Dst.
+        return true;
+      }
+      
+      StmtNodeBuilder B(TmpStore, Dst, Eng.getBuilderContext());
+      // Now bind the result of the comparison.
+      for (ExplodedNodeSet::iterator I2 = TmpStore.begin(),
+           E2 = TmpStore.end(); I2 != E2; ++I2) {
+        ExplodedNode *predNew = *I2;
+        ProgramStateRef stateNew = predNew->getState();
+        // Check for 'void' return type if we have a bogus function prototype.
+        SVal Res = UnknownVal();
+        QualType T = CE->getType();
+        if (!T->isVoidType())
+          Res = Eng.getSValBuilder().makeTruthVal(true, T);
+        B.generateNode(CE, predNew, stateNew->BindExpr(CE, LCtx, Res),
+                       false, this);
+      }
+    }
+
+    // Were they not equal?
+    if (ProgramStateRef stateNotEqual = stateLoad->assume(Cmp, false)) {
+      // Check for 'void' return type if we have a bogus function prototype.
+      SVal Res = UnknownVal();
+      QualType T = CE->getType();
+      if (!T->isVoidType())
+        Res = Eng.getSValBuilder().makeTruthVal(false, CE->getType());
+      StmtNodeBuilder B(N, Dst, Eng.getBuilderContext());    
+      B.generateNode(CE, N, stateNotEqual->BindExpr(CE, LCtx, Res),
+                     false, this);
+    }
+  }
+
+  return true;
+}
+
+void ento::registerOSAtomicChecker(CheckerManager &mgr) {
+  mgr.registerChecker<OSAtomicChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
new file mode 100644
index 0000000..777e9ea
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
@@ -0,0 +1,96 @@
+//== ObjCAtSyncChecker.cpp - nil mutex checker for @synchronized -*- C++ -*--=//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines ObjCAtSyncChecker, a builtin check that checks for null pointers
+// used as mutexes for @synchronized.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Checkers/DereferenceChecker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class ObjCAtSyncChecker
+    : public Checker< check::PreStmt<ObjCAtSynchronizedStmt> > {
+  mutable OwningPtr<BuiltinBug> BT_null;
+  mutable OwningPtr<BuiltinBug> BT_undef;
+
+public:
+  void checkPreStmt(const ObjCAtSynchronizedStmt *S, CheckerContext &C) const;
+};
+} // end anonymous namespace
+
+void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
+                                     CheckerContext &C) const {
+
+  const Expr *Ex = S->getSynchExpr();
+  ProgramStateRef state = C.getState();
+  SVal V = state->getSVal(Ex, C.getLocationContext());
+
+  // Uninitialized value used for the mutex?
+  if (isa<UndefinedVal>(V)) {
+    if (ExplodedNode *N = C.generateSink()) {
+      if (!BT_undef)
+        BT_undef.reset(new BuiltinBug("Uninitialized value used as mutex "
+                                  "for @synchronized"));
+      BugReport *report =
+        new BugReport(*BT_undef, BT_undef->getDescription(), N);
+      report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Ex,
+                                                                      report));
+      C.EmitReport(report);
+    }
+    return;
+  }
+
+  if (V.isUnknown())
+    return;
+
+  // Check for null mutexes.
+  ProgramStateRef notNullState, nullState;
+  llvm::tie(notNullState, nullState) = state->assume(cast<DefinedSVal>(V));
+
+  if (nullState) {
+    if (!notNullState) {
+      // Generate an error node.  This isn't a sink since
+      // a null mutex just means no synchronization occurs.
+      if (ExplodedNode *N = C.addTransition(nullState)) {
+        if (!BT_null)
+          BT_null.reset(new BuiltinBug("Nil value used as mutex for @synchronized() "
+                                   "(no synchronization will occur)"));
+        BugReport *report =
+          new BugReport(*BT_null, BT_null->getDescription(), N);
+        report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Ex,
+                                                                        report));
+
+        C.EmitReport(report);
+        return;
+      }
+    }
+    // Don't add a transition for 'nullState'.  If the value is
+    // under-constrained to be null or non-null, assume it is non-null
+    // afterwards.
+  }
+
+  if (notNullState)
+    C.addTransition(notNullState);
+}
+
+void ento::registerObjCAtSyncChecker(CheckerManager &mgr) {
+  if (mgr.getLangOpts().ObjC2)
+    mgr.registerChecker<ObjCAtSyncChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp
new file mode 100644
index 0000000..f2929c0
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp
@@ -0,0 +1,174 @@
+//== ObjCContainersASTChecker.cpp - CoreFoundation containers API *- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// An AST checker that looks for common pitfalls when using 'CFArray',
+// 'CFDictionary', 'CFSet' APIs.
+//
+//===----------------------------------------------------------------------===//
+#include "ClangSACheckers.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class WalkAST : public StmtVisitor<WalkAST> {
+  BugReporter &BR;
+  AnalysisDeclContext* AC;
+  ASTContext &ASTC;
+  uint64_t PtrWidth;
+
+  static const unsigned InvalidArgIndex = UINT_MAX;
+
+  /// Check if the type has pointer size (very conservative).
+  inline bool isPointerSize(const Type *T) {
+    if (!T)
+      return true;
+    if (T->isIncompleteType())
+      return true;
+    return (ASTC.getTypeSize(T) == PtrWidth);
+  }
+
+  /// Check if the type is a pointer/array to pointer sized values.
+  inline bool hasPointerToPointerSizedType(const Expr *E) {
+    QualType T = E->getType();
+
+    // The type could be either a pointer or array.
+    const Type *TP = T.getTypePtr();
+    QualType PointeeT = TP->getPointeeType();
+    if (!PointeeT.isNull()) {
+      // If the type is a pointer to an array, check the size of the array
+      // elements. To avoid false positives coming from assumption that the
+      // values x and &x are equal when x is an array.
+      if (const Type *TElem = PointeeT->getArrayElementTypeNoTypeQual())
+        if (isPointerSize(TElem))
+          return true;
+
+      // Else, check the pointee size.
+      return isPointerSize(PointeeT.getTypePtr());
+    }
+
+    if (const Type *TElem = TP->getArrayElementTypeNoTypeQual())
+      return isPointerSize(TElem);
+
+    // The type must be an array/pointer type.
+
+    // This could be a null constant, which is allowed.
+    if (E->isNullPointerConstant(ASTC, Expr::NPC_ValueDependentIsNull))
+      return true;
+    return false;
+  }
+
+public:
+  WalkAST(BugReporter &br, AnalysisDeclContext* ac)
+  : BR(br), AC(ac), ASTC(AC->getASTContext()),
+    PtrWidth(ASTC.getTargetInfo().getPointerWidth(0)) {}
+
+  // Statement visitor methods.
+  void VisitChildren(Stmt *S);
+  void VisitStmt(Stmt *S) { VisitChildren(S); }
+  void VisitCallExpr(CallExpr *CE);
+};
+} // end anonymous namespace
+
+static StringRef getCalleeName(CallExpr *CE) {
+  const FunctionDecl *FD = CE->getDirectCallee();
+  if (!FD)
+    return StringRef();
+
+  IdentifierInfo *II = FD->getIdentifier();
+  if (!II)   // if no identifier, not a simple C function
+    return StringRef();
+
+  return II->getName();
+}
+
+void WalkAST::VisitCallExpr(CallExpr *CE) {
+  StringRef Name = getCalleeName(CE);
+  if (Name.empty())
+    return;
+
+  const Expr *Arg = 0;
+  unsigned ArgNum = InvalidArgIndex;
+
+  if (Name.equals("CFArrayCreate") || Name.equals("CFSetCreate")) {
+    ArgNum = 1;
+    Arg = CE->getArg(ArgNum)->IgnoreParenCasts();
+    if (hasPointerToPointerSizedType(Arg))
+        return;
+  }
+
+  if (Arg == 0 && Name.equals("CFDictionaryCreate")) {
+    // Check first argument.
+    ArgNum = 1;
+    Arg = CE->getArg(ArgNum)->IgnoreParenCasts();
+    if (hasPointerToPointerSizedType(Arg)) {
+      // Check second argument.
+      ArgNum = 2;
+      Arg = CE->getArg(ArgNum)->IgnoreParenCasts();
+      if (hasPointerToPointerSizedType(Arg))
+        // Both are good, return.
+        return;
+    }
+  }
+
+  if (ArgNum != InvalidArgIndex) {
+    assert(ArgNum == 1 || ArgNum == 2);
+
+    SmallString<256> BufName;
+    llvm::raw_svector_ostream OsName(BufName);
+    assert(ArgNum == 1 || ArgNum == 2);
+    OsName << " Invalid use of '" << Name << "'" ;
+
+    SmallString<256> Buf;
+    llvm::raw_svector_ostream Os(Buf);
+    Os << " The "<< ((ArgNum == 1) ? "first" : "second") << " argument to '"
+        << Name << "' must be a C array of pointer-sized values, not '"
+        << Arg->getType().getAsString() << "'";
+
+    SourceRange R = Arg->getSourceRange();
+    PathDiagnosticLocation CELoc =
+        PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
+    BR.EmitBasicReport(AC->getDecl(),
+                       OsName.str(), categories::CoreFoundationObjectiveC,
+                       Os.str(), CELoc, &R, 1);
+  }
+
+  // Recurse and check children.
+  VisitChildren(CE);
+}
+
+void WalkAST::VisitChildren(Stmt *S) {
+  for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
+    if (Stmt *child = *I)
+      Visit(child);
+}
+
+namespace {
+class ObjCContainersASTChecker : public Checker<check::ASTCodeBody> {
+public:
+
+  void checkASTCodeBody(const Decl *D, AnalysisManager& Mgr,
+                        BugReporter &BR) const {
+    WalkAST walker(BR, Mgr.getAnalysisDeclContext(D));
+    walker.Visit(D->getBody());
+  }
+};
+}
+
+void ento::registerObjCContainersASTChecker(CheckerManager &mgr) {
+  mgr.registerChecker<ObjCContainersASTChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
new file mode 100644
index 0000000..f4655b6
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
@@ -0,0 +1,159 @@
+//== ObjCContainersChecker.cpp - Path sensitive checker for CFArray *- C++ -*=//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Performs path sensitive checks of Core Foundation static containers like
+// CFArray.
+// 1) Check for buffer overflows:
+//      In CFArrayGetArrayAtIndex( myArray, index), if the index is outside the
+//      index space of theArray (0 to N-1 inclusive (where N is the count of
+//      theArray), the behavior is undefined.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/AST/ParentMap.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class ObjCContainersChecker : public Checker< check::PreStmt<CallExpr>,
+                                             check::PostStmt<CallExpr> > {
+  mutable OwningPtr<BugType> BT;
+  inline void initBugType() const {
+    if (!BT)
+      BT.reset(new BugType("CFArray API",
+                           categories::CoreFoundationObjectiveC));
+  }
+
+  inline SymbolRef getArraySym(const Expr *E, CheckerContext &C) const {
+    SVal ArrayRef = C.getState()->getSVal(E, C.getLocationContext());
+    SymbolRef ArraySym = ArrayRef.getAsSymbol();
+    return ArraySym;
+  }
+
+  void addSizeInfo(const Expr *Array, const Expr *Size,
+                   CheckerContext &C) const;
+
+public:
+  /// A tag to id this checker.
+  static void *getTag() { static int Tag; return &Tag; }
+
+  void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
+  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
+};
+} // end anonymous namespace
+
+// ProgramState trait - a map from array symbol to it's state.
+typedef llvm::ImmutableMap<SymbolRef, DefinedSVal> ArraySizeM;
+
+namespace { struct ArraySizeMap {}; }
+namespace clang { namespace ento {
+template<> struct ProgramStateTrait<ArraySizeMap>
+    :  public ProgramStatePartialTrait<ArraySizeM > {
+  static void *GDMIndex() { return ObjCContainersChecker::getTag(); }
+};
+}}
+
+void ObjCContainersChecker::addSizeInfo(const Expr *Array, const Expr *Size,
+                                        CheckerContext &C) const {
+  ProgramStateRef State = C.getState();
+  SVal SizeV = State->getSVal(Size, C.getLocationContext());
+  // Undefined is reported by another checker.
+  if (SizeV.isUnknownOrUndef())
+    return;
+
+  // Get the ArrayRef symbol.
+  SVal ArrayRef = State->getSVal(Array, C.getLocationContext());
+  SymbolRef ArraySym = ArrayRef.getAsSymbol();
+  if (!ArraySym)
+    return;
+
+  C.addTransition(State->set<ArraySizeMap>(ArraySym, cast<DefinedSVal>(SizeV)));
+  return;
+}
+
+void ObjCContainersChecker::checkPostStmt(const CallExpr *CE,
+                                          CheckerContext &C) const {
+  StringRef Name = C.getCalleeName(CE);
+  if (Name.empty() || CE->getNumArgs() < 1)
+    return;
+
+  // Add array size information to the state.
+  if (Name.equals("CFArrayCreate")) {
+    if (CE->getNumArgs() < 3)
+      return;
+    // Note, we can visit the Create method in the post-visit because
+    // the CFIndex parameter is passed in by value and will not be invalidated
+    // by the call.
+    addSizeInfo(CE, CE->getArg(2), C);
+    return;
+  }
+
+  if (Name.equals("CFArrayGetCount")) {
+    addSizeInfo(CE->getArg(0), CE, C);
+    return;
+  }
+}
+
+void ObjCContainersChecker::checkPreStmt(const CallExpr *CE,
+                                         CheckerContext &C) const {
+  StringRef Name = C.getCalleeName(CE);
+  if (Name.empty() || CE->getNumArgs() < 2)
+    return;
+
+  // Check the array access.
+  if (Name.equals("CFArrayGetValueAtIndex")) {
+    ProgramStateRef State = C.getState();
+    // Retrieve the size.
+    // Find out if we saw this array symbol before and have information about it.
+    const Expr *ArrayExpr = CE->getArg(0);
+    SymbolRef ArraySym = getArraySym(ArrayExpr, C);
+    if (!ArraySym)
+      return;
+
+    const DefinedSVal *Size = State->get<ArraySizeMap>(ArraySym);
+
+    if (!Size)
+      return;
+
+    // Get the index.
+    const Expr *IdxExpr = CE->getArg(1);
+    SVal IdxVal = State->getSVal(IdxExpr, C.getLocationContext());
+    if (IdxVal.isUnknownOrUndef())
+      return;
+    DefinedSVal Idx = cast<DefinedSVal>(IdxVal);
+    
+    // Now, check if 'Idx in [0, Size-1]'.
+    const QualType T = IdxExpr->getType();
+    ProgramStateRef StInBound = State->assumeInBound(Idx, *Size, true, T);
+    ProgramStateRef StOutBound = State->assumeInBound(Idx, *Size, false, T);
+    if (StOutBound && !StInBound) {
+      ExplodedNode *N = C.generateSink(StOutBound);
+      if (!N)
+        return;
+      initBugType();
+      BugReport *R = new BugReport(*BT, "Index is out of bounds", N);
+      R->addRange(IdxExpr->getSourceRange());
+      C.EmitReport(R);
+      return;
+    }
+  }
+}
+
+/// Register checker.
+void ento::registerObjCContainersChecker(CheckerManager &mgr) {
+  mgr.registerChecker<ObjCContainersChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
new file mode 100644
index 0000000..97b58cf
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
@@ -0,0 +1,396 @@
+//== ObjCSelfInitChecker.cpp - Checker for 'self' initialization -*- C++ -*--=//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines ObjCSelfInitChecker, a builtin check that checks for uses of
+// 'self' before proper initialization.
+//
+//===----------------------------------------------------------------------===//
+
+// This checks initialization methods to verify that they assign 'self' to the
+// result of an initialization call (e.g. [super init], or [self initWith..])
+// before using 'self' or any instance variable.
+//
+// To perform the required checking, values are tagged with flags that indicate
+// 1) if the object is the one pointed to by 'self', and 2) if the object
+// is the result of an initializer (e.g. [super init]).
+//
+// Uses of an object that is true for 1) but not 2) trigger a diagnostic.
+// The uses that are currently checked are:
+//  - Using instance variables.
+//  - Returning the object.
+//
+// Note that we don't check for an invalid 'self' that is the receiver of an
+// obj-c message expression to cut down false positives where logging functions
+// get information from self (like its class) or doing "invalidation" on self
+// when the initialization fails.
+//
+// Because the object that 'self' points to gets invalidated when a call
+// receives a reference to 'self', the checker keeps track and passes the flags
+// for 1) and 2) to the new object that 'self' points to after the call.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/AST/ParentMap.h"
+
+using namespace clang;
+using namespace ento;
+
+static bool shouldRunOnFunctionOrMethod(const NamedDecl *ND);
+static bool isInitializationMethod(const ObjCMethodDecl *MD);
+static bool isInitMessage(const ObjCMessage &msg);
+static bool isSelfVar(SVal location, CheckerContext &C);
+
+namespace {
+class ObjCSelfInitChecker : public Checker<  check::PreObjCMessage,
+                                             check::PostObjCMessage,
+                                             check::PostStmt<ObjCIvarRefExpr>,
+                                             check::PreStmt<ReturnStmt>,
+                                             check::PreStmt<CallExpr>,
+                                             check::PostStmt<CallExpr>,
+                                             check::Location > {
+public:
+  void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const;
+  void checkPostObjCMessage(ObjCMessage msg, CheckerContext &C) const;
+  void checkPostStmt(const ObjCIvarRefExpr *E, CheckerContext &C) const;
+  void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
+  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
+  void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
+  void checkLocation(SVal location, bool isLoad, const Stmt *S,
+                     CheckerContext &C) const;
+
+  void checkPreStmt(const CallOrObjCMessage &CE, CheckerContext &C) const;
+  void checkPostStmt(const CallOrObjCMessage &CE, CheckerContext &C) const;
+
+};
+} // end anonymous namespace
+
+namespace {
+
+class InitSelfBug : public BugType {
+  const std::string desc;
+public:
+  InitSelfBug() : BugType("Missing \"self = [(super or self) init...]\"",
+                          categories::CoreFoundationObjectiveC) {}
+};
+
+} // end anonymous namespace
+
+namespace {
+enum SelfFlagEnum {
+  /// \brief No flag set.
+  SelfFlag_None = 0x0,
+  /// \brief Value came from 'self'.
+  SelfFlag_Self    = 0x1,
+  /// \brief Value came from the result of an initializer (e.g. [super init]).
+  SelfFlag_InitRes = 0x2
+};
+}
+
+typedef llvm::ImmutableMap<SymbolRef, unsigned> SelfFlag;
+namespace { struct CalledInit {}; }
+namespace { struct PreCallSelfFlags {}; }
+
+namespace clang {
+namespace ento {
+  template<>
+  struct ProgramStateTrait<SelfFlag> : public ProgramStatePartialTrait<SelfFlag> {
+    static void *GDMIndex() { static int index = 0; return &index; }
+  };
+  template <>
+  struct ProgramStateTrait<CalledInit> : public ProgramStatePartialTrait<bool> {
+    static void *GDMIndex() { static int index = 0; return &index; }
+  };
+
+  /// \brief A call receiving a reference to 'self' invalidates the object that
+  /// 'self' contains. This keeps the "self flags" assigned to the 'self'
+  /// object before the call so we can assign them to the new object that 'self'
+  /// points to after the call.
+  template <>
+  struct ProgramStateTrait<PreCallSelfFlags> : public ProgramStatePartialTrait<unsigned> {
+    static void *GDMIndex() { static int index = 0; return &index; }
+  };
+}
+}
+
+static SelfFlagEnum getSelfFlags(SVal val, ProgramStateRef state) {
+  if (SymbolRef sym = val.getAsSymbol())
+    if (const unsigned *attachedFlags = state->get<SelfFlag>(sym))
+      return (SelfFlagEnum)*attachedFlags;
+  return SelfFlag_None;
+}
+
+static SelfFlagEnum getSelfFlags(SVal val, CheckerContext &C) {
+  return getSelfFlags(val, C.getState());
+}
+
+static void addSelfFlag(ProgramStateRef state, SVal val,
+                        SelfFlagEnum flag, CheckerContext &C) {
+  // We tag the symbol that the SVal wraps.
+  if (SymbolRef sym = val.getAsSymbol())
+    C.addTransition(state->set<SelfFlag>(sym, getSelfFlags(val, C) | flag));
+}
+
+static bool hasSelfFlag(SVal val, SelfFlagEnum flag, CheckerContext &C) {
+  return getSelfFlags(val, C) & flag;
+}
+
+/// \brief Returns true of the value of the expression is the object that 'self'
+/// points to and is an object that did not come from the result of calling
+/// an initializer.
+static bool isInvalidSelf(const Expr *E, CheckerContext &C) {
+  SVal exprVal = C.getState()->getSVal(E, C.getLocationContext());
+  if (!hasSelfFlag(exprVal, SelfFlag_Self, C))
+    return false; // value did not come from 'self'.
+  if (hasSelfFlag(exprVal, SelfFlag_InitRes, C))
+    return false; // 'self' is properly initialized.
+
+  return true;
+}
+
+static void checkForInvalidSelf(const Expr *E, CheckerContext &C,
+                                const char *errorStr) {
+  if (!E)
+    return;
+  
+  if (!C.getState()->get<CalledInit>())
+    return;
+  
+  if (!isInvalidSelf(E, C))
+    return;
+  
+  // Generate an error node.
+  ExplodedNode *N = C.generateSink();
+  if (!N)
+    return;
+
+  BugReport *report =
+    new BugReport(*new InitSelfBug(), errorStr, N);
+  C.EmitReport(report);
+}
+
+void ObjCSelfInitChecker::checkPostObjCMessage(ObjCMessage msg,
+                                               CheckerContext &C) const {
+  // When encountering a message that does initialization (init rule),
+  // tag the return value so that we know later on that if self has this value
+  // then it is properly initialized.
+
+  // FIXME: A callback should disable checkers at the start of functions.
+  if (!shouldRunOnFunctionOrMethod(dyn_cast<NamedDecl>(
+                                C.getCurrentAnalysisDeclContext()->getDecl())))
+    return;
+
+  if (isInitMessage(msg)) {
+    // Tag the return value as the result of an initializer.
+    ProgramStateRef state = C.getState();
+    
+    // FIXME this really should be context sensitive, where we record
+    // the current stack frame (for IPA).  Also, we need to clean this
+    // value out when we return from this method.
+    state = state->set<CalledInit>(true);
+    
+    SVal V = state->getSVal(msg.getMessageExpr(), C.getLocationContext());
+    addSelfFlag(state, V, SelfFlag_InitRes, C);
+    return;
+  }
+
+  CallOrObjCMessage MsgWrapper(msg, C.getState(), C.getLocationContext());
+  checkPostStmt(MsgWrapper, C);
+
+  // We don't check for an invalid 'self' in an obj-c message expression to cut
+  // down false positives where logging functions get information from self
+  // (like its class) or doing "invalidation" on self when the initialization
+  // fails.
+}
+
+void ObjCSelfInitChecker::checkPostStmt(const ObjCIvarRefExpr *E,
+                                        CheckerContext &C) const {
+  // FIXME: A callback should disable checkers at the start of functions.
+  if (!shouldRunOnFunctionOrMethod(dyn_cast<NamedDecl>(
+                                 C.getCurrentAnalysisDeclContext()->getDecl())))
+    return;
+
+  checkForInvalidSelf(E->getBase(), C,
+    "Instance variable used while 'self' is not set to the result of "
+                                                 "'[(super or self) init...]'");
+}
+
+void ObjCSelfInitChecker::checkPreStmt(const ReturnStmt *S,
+                                       CheckerContext &C) const {
+  // FIXME: A callback should disable checkers at the start of functions.
+  if (!shouldRunOnFunctionOrMethod(dyn_cast<NamedDecl>(
+                                 C.getCurrentAnalysisDeclContext()->getDecl())))
+    return;
+
+  checkForInvalidSelf(S->getRetValue(), C,
+    "Returning 'self' while it is not set to the result of "
+                                                 "'[(super or self) init...]'");
+}
+
+// When a call receives a reference to 'self', [Pre/Post]VisitGenericCall pass
+// the SelfFlags from the object 'self' point to before the call, to the new
+// object after the call. This is to avoid invalidation of 'self' by logging
+// functions.
+// Another common pattern in classes with multiple initializers is to put the
+// subclass's common initialization bits into a static function that receives
+// the value of 'self', e.g:
+// @code
+//   if (!(self = [super init]))
+//     return nil;
+//   if (!(self = _commonInit(self)))
+//     return nil;
+// @endcode
+// Until we can use inter-procedural analysis, in such a call, transfer the
+// SelfFlags to the result of the call.
+
+void ObjCSelfInitChecker::checkPreStmt(const CallExpr *CE,
+                                       CheckerContext &C) const {
+  CallOrObjCMessage CEWrapper(CE, C.getState(), C.getLocationContext());
+  checkPreStmt(CEWrapper, C);
+}
+
+void ObjCSelfInitChecker::checkPostStmt(const CallExpr *CE,
+                                        CheckerContext &C) const {
+  CallOrObjCMessage CEWrapper(CE, C.getState(), C.getLocationContext());
+  checkPostStmt(CEWrapper, C);
+}
+
+void ObjCSelfInitChecker::checkPreObjCMessage(ObjCMessage Msg,
+                                              CheckerContext &C) const {
+  CallOrObjCMessage MsgWrapper(Msg, C.getState(), C.getLocationContext());
+  checkPreStmt(MsgWrapper, C);
+}
+
+void ObjCSelfInitChecker::checkPreStmt(const CallOrObjCMessage &CE,
+                                       CheckerContext &C) const {
+  ProgramStateRef state = C.getState();
+  unsigned NumArgs = CE.getNumArgs();
+  // If we passed 'self' as and argument to the call, record it in the state
+  // to be propagated after the call.
+  // Note, we could have just given up, but try to be more optimistic here and
+  // assume that the functions are going to continue initialization or will not
+  // modify self.
+  for (unsigned i = 0; i < NumArgs; ++i) {
+    SVal argV = CE.getArgSVal(i);
+    if (isSelfVar(argV, C)) {
+      unsigned selfFlags = getSelfFlags(state->getSVal(cast<Loc>(argV)), C);
+      C.addTransition(state->set<PreCallSelfFlags>(selfFlags));
+      return;
+    } else if (hasSelfFlag(argV, SelfFlag_Self, C)) {
+      unsigned selfFlags = getSelfFlags(argV, C);
+      C.addTransition(state->set<PreCallSelfFlags>(selfFlags));
+      return;
+    }
+  }
+}
+
+void ObjCSelfInitChecker::checkPostStmt(const CallOrObjCMessage &CE,
+                                        CheckerContext &C) const {
+  ProgramStateRef state = C.getState();
+  unsigned NumArgs = CE.getNumArgs();
+  for (unsigned i = 0; i < NumArgs; ++i) {
+    SVal argV = CE.getArgSVal(i);
+    if (isSelfVar(argV, C)) {
+      // If the address of 'self' is being passed to the call, assume that the
+      // 'self' after the call will have the same flags.
+      // EX: log(&self)
+      SelfFlagEnum prevFlags = (SelfFlagEnum)state->get<PreCallSelfFlags>();
+      state = state->remove<PreCallSelfFlags>();
+      addSelfFlag(state, state->getSVal(cast<Loc>(argV)), prevFlags, C);
+      return;
+    } else if (hasSelfFlag(argV, SelfFlag_Self, C)) {
+      // If 'self' is passed to the call by value, assume that the function
+      // returns 'self'. So assign the flags, which were set on 'self' to the
+      // return value.
+      // EX: self = performMoreInitialization(self)
+      SelfFlagEnum prevFlags = (SelfFlagEnum)state->get<PreCallSelfFlags>();
+      state = state->remove<PreCallSelfFlags>();
+      const Expr *CallExpr = CE.getOriginExpr();
+      if (CallExpr)
+        addSelfFlag(state, state->getSVal(CallExpr, C.getLocationContext()),
+                                          prevFlags, C);
+      return;
+    }
+  }
+}
+
+void ObjCSelfInitChecker::checkLocation(SVal location, bool isLoad,
+                                        const Stmt *S,
+                                        CheckerContext &C) const {
+  // Tag the result of a load from 'self' so that we can easily know that the
+  // value is the object that 'self' points to.
+  ProgramStateRef state = C.getState();
+  if (isSelfVar(location, C))
+    addSelfFlag(state, state->getSVal(cast<Loc>(location)), SelfFlag_Self, C);
+}
+
+// FIXME: A callback should disable checkers at the start of functions.
+static bool shouldRunOnFunctionOrMethod(const NamedDecl *ND) {
+  if (!ND)
+    return false;
+
+  const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(ND);
+  if (!MD)
+    return false;
+  if (!isInitializationMethod(MD))
+    return false;
+
+  // self = [super init] applies only to NSObject subclasses.
+  // For instance, NSProxy doesn't implement -init.
+  ASTContext &Ctx = MD->getASTContext();
+  IdentifierInfo* NSObjectII = &Ctx.Idents.get("NSObject");
+  ObjCInterfaceDecl *ID = MD->getClassInterface()->getSuperClass();
+  for ( ; ID ; ID = ID->getSuperClass()) {
+    IdentifierInfo *II = ID->getIdentifier();
+
+    if (II == NSObjectII)
+      break;
+  }
+  if (!ID)
+    return false;
+
+  return true;
+}
+
+/// \brief Returns true if the location is 'self'.
+static bool isSelfVar(SVal location, CheckerContext &C) {
+  AnalysisDeclContext *analCtx = C.getCurrentAnalysisDeclContext(); 
+  if (!analCtx->getSelfDecl())
+    return false;
+  if (!isa<loc::MemRegionVal>(location))
+    return false;
+
+  loc::MemRegionVal MRV = cast<loc::MemRegionVal>(location);
+  if (const DeclRegion *DR = dyn_cast<DeclRegion>(MRV.stripCasts()))
+    return (DR->getDecl() == analCtx->getSelfDecl());
+
+  return false;
+}
+
+static bool isInitializationMethod(const ObjCMethodDecl *MD) {
+  return MD->getMethodFamily() == OMF_init;
+}
+
+static bool isInitMessage(const ObjCMessage &msg) {
+  return msg.getMethodFamily() == OMF_init;
+}
+
+//===----------------------------------------------------------------------===//
+// Registration.
+//===----------------------------------------------------------------------===//
+
+void ento::registerObjCSelfInitChecker(CheckerManager &mgr) {
+  mgr.registerChecker<ObjCSelfInitChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp
new file mode 100644
index 0000000..4718dc7
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp
@@ -0,0 +1,186 @@
+//==- ObjCUnusedIVarsChecker.cpp - Check for unused ivars --------*- 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 CheckObjCUnusedIvars, a checker that
+//  analyzes an Objective-C class's interface/implementation to determine if it
+//  has any ivars that are never accessed.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+
+using namespace clang;
+using namespace ento;
+
+enum IVarState { Unused, Used };
+typedef llvm::DenseMap<const ObjCIvarDecl*,IVarState> IvarUsageMap;
+
+static void Scan(IvarUsageMap& M, const Stmt *S) {
+  if (!S)
+    return;
+
+  if (const ObjCIvarRefExpr *Ex = dyn_cast<ObjCIvarRefExpr>(S)) {
+    const ObjCIvarDecl *D = Ex->getDecl();
+    IvarUsageMap::iterator I = M.find(D);
+    if (I != M.end())
+      I->second = Used;
+    return;
+  }
+
+  // Blocks can reference an instance variable of a class.
+  if (const BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
+    Scan(M, BE->getBody());
+    return;
+  }
+
+  for (Stmt::const_child_iterator I=S->child_begin(),E=S->child_end(); I!=E;++I)
+    Scan(M, *I);
+}
+
+static void Scan(IvarUsageMap& M, const ObjCPropertyImplDecl *D) {
+  if (!D)
+    return;
+
+  const ObjCIvarDecl *ID = D->getPropertyIvarDecl();
+
+  if (!ID)
+    return;
+
+  IvarUsageMap::iterator I = M.find(ID);
+  if (I != M.end())
+    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);
+    }
+  }
+}
+
+static void Scan(IvarUsageMap &M, const DeclContext *C, const FileID FID,
+                 SourceManager &SM) {
+  for (DeclContext::decl_iterator I=C->decls_begin(), E=C->decls_end();
+       I!=E; ++I)
+    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
+      SourceLocation L = FD->getLocStart();
+      if (SM.getFileID(L) == FID)
+        Scan(M, FD->getBody());
+    }
+}
+
+static void checkObjCUnusedIvar(const ObjCImplementationDecl *D,
+                                BugReporter &BR) {
+
+  const ObjCInterfaceDecl *ID = D->getClassInterface();
+  IvarUsageMap M;
+
+  // Iterate over the ivars.
+  for (ObjCInterfaceDecl::ivar_iterator I=ID->ivar_begin(),
+        E=ID->ivar_end(); I!=E; ++I) {
+
+    const ObjCIvarDecl *ID = *I;
+
+    // Ignore ivars that...
+    // (a) aren't private
+    // (b) explicitly marked unused
+    // (c) are iboutlets
+    // (d) are unnamed bitfields
+    if (ID->getAccessControl() != ObjCIvarDecl::Private ||
+        ID->getAttr<UnusedAttr>() || ID->getAttr<IBOutletAttr>() ||
+        ID->getAttr<IBOutletCollectionAttr>() ||
+        ID->isUnnamedBitfield())
+      continue;
+
+    M[ID] = Unused;
+  }
+
+  if (M.empty())
+    return;
+
+  // Now scan the implementation declaration.
+  Scan(M, D);
+
+  // Any potentially unused ivars?
+  bool hasUnused = false;
+  for (IvarUsageMap::iterator I = M.begin(), E = M.end(); I!=E; ++I)
+    if (I->second == Unused) {
+      hasUnused = true;
+      break;
+    }
+
+  if (!hasUnused)
+    return;
+
+  // We found some potentially unused ivars.  Scan the entire translation unit
+  // for functions inside the @implementation that reference these ivars.
+  // FIXME: In the future hopefully we can just use the lexical DeclContext
+  // to go from the ObjCImplementationDecl to the lexically "nested"
+  // C functions.
+  SourceManager &SM = BR.getSourceManager();
+  Scan(M, D->getDeclContext(), SM.getFileID(D->getLocation()), SM);
+
+  // Find ivars that are unused.
+  for (IvarUsageMap::iterator I = M.begin(), E = M.end(); I!=E; ++I)
+    if (I->second == Unused) {
+      std::string sbuf;
+      llvm::raw_string_ostream os(sbuf);
+      os << "Instance variable '" << *I->first << "' in class '" << *ID
+         << "' is never used by the methods in its @implementation "
+            "(although it may be used by category methods).";
+
+      PathDiagnosticLocation L =
+        PathDiagnosticLocation::create(I->first, BR.getSourceManager());
+      BR.EmitBasicReport(D, "Unused instance variable", "Optimization",
+                         os.str(), L);
+    }
+}
+
+//===----------------------------------------------------------------------===//
+// ObjCUnusedIvarsChecker
+//===----------------------------------------------------------------------===//
+
+namespace {
+class ObjCUnusedIvarsChecker : public Checker<
+                                      check::ASTDecl<ObjCImplementationDecl> > {
+public:
+  void checkASTDecl(const ObjCImplementationDecl *D, AnalysisManager& mgr,
+                    BugReporter &BR) const {
+    checkObjCUnusedIvar(D, BR);
+  }
+};
+}
+
+void ento::registerObjCUnusedIvarsChecker(CheckerManager &mgr) {
+  mgr.registerChecker<ObjCUnusedIvarsChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
new file mode 100644
index 0000000..fe4845b
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
@@ -0,0 +1,69 @@
+//=== PointerArithChecker.cpp - Pointer arithmetic checker -----*- C++ -*--===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This files defines PointerArithChecker, a builtin checker that checks for
+// pointer arithmetic on locations other than array elements.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class PointerArithChecker 
+  : public Checker< check::PreStmt<BinaryOperator> > {
+  mutable OwningPtr<BuiltinBug> BT;
+
+public:
+  void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
+};
+}
+
+void PointerArithChecker::checkPreStmt(const BinaryOperator *B,
+                                       CheckerContext &C) const {
+  if (B->getOpcode() != BO_Sub && B->getOpcode() != BO_Add)
+    return;
+
+  ProgramStateRef state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal LV = state->getSVal(B->getLHS(), LCtx);
+  SVal RV = state->getSVal(B->getRHS(), LCtx);
+
+  const MemRegion *LR = LV.getAsRegion();
+
+  if (!LR || !RV.isConstant())
+    return;
+
+  // If pointer arithmetic is done on variables of non-array type, this often
+  // means behavior rely on memory organization, which is dangerous.
+  if (isa<VarRegion>(LR) || isa<CodeTextRegion>(LR) || 
+      isa<CompoundLiteralRegion>(LR)) {
+
+    if (ExplodedNode *N = C.addTransition()) {
+      if (!BT)
+        BT.reset(new BuiltinBug("Dangerous pointer arithmetic",
+                            "Pointer arithmetic done on non-array variables "
+                            "means reliance on memory layout, which is "
+                            "dangerous."));
+      BugReport *R = new BugReport(*BT, BT->getDescription(), N);
+      R->addRange(B->getSourceRange());
+      C.EmitReport(R);
+    }
+  }
+}
+
+void ento::registerPointerArithChecker(CheckerManager &mgr) {
+  mgr.registerChecker<PointerArithChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
new file mode 100644
index 0000000..fa5c6a3
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
@@ -0,0 +1,76 @@
+//=== PointerSubChecker.cpp - Pointer subtraction checker ------*- C++ -*--===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This files defines PointerSubChecker, a builtin checker that checks for
+// pointer subtractions on two pointers pointing to different memory chunks. 
+// This check corresponds to CWE-469.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class PointerSubChecker 
+  : public Checker< check::PreStmt<BinaryOperator> > {
+  mutable OwningPtr<BuiltinBug> BT;
+
+public:
+  void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
+};
+}
+
+void PointerSubChecker::checkPreStmt(const BinaryOperator *B,
+                                     CheckerContext &C) const {
+  // When doing pointer subtraction, if the two pointers do not point to the
+  // same memory chunk, emit a warning.
+  if (B->getOpcode() != BO_Sub)
+    return;
+
+  ProgramStateRef state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal LV = state->getSVal(B->getLHS(), LCtx);
+  SVal RV = state->getSVal(B->getRHS(), LCtx);
+
+  const MemRegion *LR = LV.getAsRegion();
+  const MemRegion *RR = RV.getAsRegion();
+
+  if (!(LR && RR))
+    return;
+
+  const MemRegion *BaseLR = LR->getBaseRegion();
+  const MemRegion *BaseRR = RR->getBaseRegion();
+
+  if (BaseLR == BaseRR)
+    return;
+
+  // Allow arithmetic on different symbolic regions.
+  if (isa<SymbolicRegion>(BaseLR) || isa<SymbolicRegion>(BaseRR))
+    return;
+
+  if (ExplodedNode *N = C.addTransition()) {
+    if (!BT)
+      BT.reset(new BuiltinBug("Pointer subtraction", 
+                          "Subtraction of two pointers that do not point to "
+                          "the same memory chunk may cause incorrect result."));
+    BugReport *R = new BugReport(*BT, BT->getDescription(), N);
+    R->addRange(B->getSourceRange());
+    C.EmitReport(R);
+  }
+}
+
+void ento::registerPointerSubChecker(CheckerManager &mgr) {
+  mgr.registerChecker<PointerSubChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
new file mode 100644
index 0000000..2d018ef
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
@@ -0,0 +1,198 @@
+//===--- PthreadLockChecker.cpp - Check for locking problems ---*- C++ -*--===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines PthreadLockChecker, a simple lock -> unlock checker.
+// Also handles XNU locks, which behave similarly enough to share code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "llvm/ADT/ImmutableList.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class PthreadLockChecker : public Checker< check::PostStmt<CallExpr> > {
+  mutable OwningPtr<BugType> BT_doublelock;
+  mutable OwningPtr<BugType> BT_lor;
+  enum LockingSemantics {
+    NotApplicable = 0,
+    PthreadSemantics,
+    XNUSemantics
+  };
+public:
+  void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
+    
+  void AcquireLock(CheckerContext &C, const CallExpr *CE, SVal lock,
+                   bool isTryLock, enum LockingSemantics semantics) const;
+    
+  void ReleaseLock(CheckerContext &C, const CallExpr *CE, SVal lock) const;
+};
+} // end anonymous namespace
+
+// GDM Entry for tracking lock state.
+namespace { class LockSet {}; }
+namespace clang {
+namespace ento {
+template <> struct ProgramStateTrait<LockSet> :
+  public ProgramStatePartialTrait<llvm::ImmutableList<const MemRegion*> > {
+    static void *GDMIndex() { static int x = 0; return &x; }
+};
+} // end of ento (ProgramState) namespace
+} // end clang namespace
+
+
+void PthreadLockChecker::checkPostStmt(const CallExpr *CE,
+                                       CheckerContext &C) const {
+  ProgramStateRef state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
+  StringRef FName = C.getCalleeName(CE);
+  if (FName.empty())
+    return;
+
+  if (CE->getNumArgs() != 1)
+    return;
+
+  if (FName == "pthread_mutex_lock" ||
+      FName == "pthread_rwlock_rdlock" ||
+      FName == "pthread_rwlock_wrlock")
+    AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx),
+                false, PthreadSemantics);
+  else if (FName == "lck_mtx_lock" ||
+           FName == "lck_rw_lock_exclusive" ||
+           FName == "lck_rw_lock_shared") 
+    AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx),
+                false, XNUSemantics);
+  else if (FName == "pthread_mutex_trylock" ||
+           FName == "pthread_rwlock_tryrdlock" ||
+           FName == "pthread_rwlock_tryrwlock")
+    AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx),
+                true, PthreadSemantics);
+  else if (FName == "lck_mtx_try_lock" ||
+           FName == "lck_rw_try_lock_exclusive" ||
+           FName == "lck_rw_try_lock_shared")
+    AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx),
+                true, XNUSemantics);
+  else if (FName == "pthread_mutex_unlock" ||
+           FName == "pthread_rwlock_unlock" ||
+           FName == "lck_mtx_unlock" ||
+           FName == "lck_rw_done")
+    ReleaseLock(C, CE, state->getSVal(CE->getArg(0), LCtx));
+}
+
+void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE,
+                                     SVal lock, bool isTryLock,
+                                     enum LockingSemantics semantics) const {
+  
+  const MemRegion *lockR = lock.getAsRegion();
+  if (!lockR)
+    return;
+  
+  ProgramStateRef state = C.getState();
+  
+  SVal X = state->getSVal(CE, C.getLocationContext());
+  if (X.isUnknownOrUndef())
+    return;
+  
+  DefinedSVal retVal = cast<DefinedSVal>(X);
+
+  if (state->contains<LockSet>(lockR)) {
+    if (!BT_doublelock)
+      BT_doublelock.reset(new BugType("Double locking", "Lock checker"));
+    ExplodedNode *N = C.generateSink();
+    if (!N)
+      return;
+    BugReport *report = new BugReport(*BT_doublelock,
+                                                      "This lock has already "
+                                                      "been acquired", N);
+    report->addRange(CE->getArg(0)->getSourceRange());
+    C.EmitReport(report);
+    return;
+  }
+
+  ProgramStateRef lockSucc = state;
+  if (isTryLock) {
+    // Bifurcate the state, and allow a mode where the lock acquisition fails.
+    ProgramStateRef lockFail;
+    switch (semantics) {
+    case PthreadSemantics:
+      llvm::tie(lockFail, lockSucc) = state->assume(retVal);    
+      break;
+    case XNUSemantics:
+      llvm::tie(lockSucc, lockFail) = state->assume(retVal);    
+      break;
+    default:
+      llvm_unreachable("Unknown tryLock locking semantics");
+    }
+    assert(lockFail && lockSucc);
+    C.addTransition(lockFail);
+
+  } else if (semantics == PthreadSemantics) {
+    // Assume that the return value was 0.
+    lockSucc = state->assume(retVal, false);
+    assert(lockSucc);
+
+  } else {
+    // XNU locking semantics return void on non-try locks
+    assert((semantics == XNUSemantics) && "Unknown locking semantics");
+    lockSucc = state;
+  }
+  
+  // Record that the lock was acquired.  
+  lockSucc = lockSucc->add<LockSet>(lockR);
+  C.addTransition(lockSucc);
+}
+
+void PthreadLockChecker::ReleaseLock(CheckerContext &C, const CallExpr *CE,
+                                     SVal lock) const {
+
+  const MemRegion *lockR = lock.getAsRegion();
+  if (!lockR)
+    return;
+  
+  ProgramStateRef state = C.getState();
+  llvm::ImmutableList<const MemRegion*> LS = state->get<LockSet>();
+
+  // FIXME: Better analysis requires IPA for wrappers.
+  // FIXME: check for double unlocks
+  if (LS.isEmpty())
+    return;
+  
+  const MemRegion *firstLockR = LS.getHead();
+  if (firstLockR != lockR) {
+    if (!BT_lor)
+      BT_lor.reset(new BugType("Lock order reversal", "Lock checker"));
+    ExplodedNode *N = C.generateSink();
+    if (!N)
+      return;
+    BugReport *report = new BugReport(*BT_lor,
+                                                      "This was not the most "
+                                                      "recently acquired lock. "
+                                                      "Possible lock order "
+                                                      "reversal", N);
+    report->addRange(CE->getArg(0)->getSourceRange());
+    C.EmitReport(report);
+    return;
+  }
+
+  // Record that the lock was released. 
+  state = state->set<LockSet>(LS.getTail());
+  C.addTransition(state);
+}
+
+
+void ento::registerPthreadLockChecker(CheckerManager &mgr) {
+  mgr.registerChecker<PthreadLockChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
new file mode 100644
index 0000000..b569e41
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
@@ -0,0 +1,3702 @@
+//==-- RetainCountChecker.cpp - Checks for leaks and other issues -*- 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 the methods for RetainCountChecker, which implements
+//  a reference count checker for Core Foundation and Cocoa on (Mac OS X).
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ImmutableList.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include <cstdarg>
+
+using namespace clang;
+using namespace ento;
+using llvm::StrInStrNoCase;
+
+namespace {
+/// Wrapper around different kinds of node builder, so that helper functions
+/// can have a common interface.
+class GenericNodeBuilderRefCount {
+  CheckerContext *C;
+  const ProgramPointTag *tag;
+public:
+  GenericNodeBuilderRefCount(CheckerContext &c,
+                             const ProgramPointTag *t = 0)
+  : C(&c), tag(t){}
+
+  ExplodedNode *MakeNode(ProgramStateRef state, ExplodedNode *Pred,
+                         bool MarkAsSink = false) {
+    return C->addTransition(state, Pred, tag, MarkAsSink);
+  }
+};
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Primitives used for constructing summaries for function/method calls.
+//===----------------------------------------------------------------------===//
+
+/// ArgEffect is used to summarize a function/method call's effect on a
+/// particular argument.
+enum ArgEffect { DoNothing, Autorelease, Dealloc, DecRef, DecRefMsg,
+                 DecRefBridgedTransfered,
+                 IncRefMsg, IncRef, MakeCollectable, MayEscape,
+                 NewAutoreleasePool, SelfOwn, StopTracking };
+
+namespace llvm {
+template <> struct FoldingSetTrait<ArgEffect> {
+static inline void Profile(const ArgEffect X, FoldingSetNodeID& ID) {
+  ID.AddInteger((unsigned) X);
+}
+};
+} // end llvm namespace
+
+/// ArgEffects summarizes the effects of a function/method call on all of
+/// its arguments.
+typedef llvm::ImmutableMap<unsigned,ArgEffect> ArgEffects;
+
+namespace {
+
+///  RetEffect is used to summarize a function/method call's behavior with
+///  respect to its return value.
+class RetEffect {
+public:
+  enum Kind { NoRet, OwnedSymbol, OwnedAllocatedSymbol,
+              NotOwnedSymbol, GCNotOwnedSymbol, ARCNotOwnedSymbol,
+              OwnedWhenTrackedReceiver };
+
+  enum ObjKind { CF, ObjC, AnyObj };
+
+private:
+  Kind K;
+  ObjKind O;
+
+  RetEffect(Kind k, ObjKind o = AnyObj) : K(k), O(o) {}
+
+public:
+  Kind getKind() const { return K; }
+
+  ObjKind getObjKind() const { return O; }
+
+  bool isOwned() const {
+    return K == OwnedSymbol || K == OwnedAllocatedSymbol ||
+           K == OwnedWhenTrackedReceiver;
+  }
+
+  bool operator==(const RetEffect &Other) const {
+    return K == Other.K && O == Other.O;
+  }
+
+  static RetEffect MakeOwnedWhenTrackedReceiver() {
+    return RetEffect(OwnedWhenTrackedReceiver, ObjC);
+  }
+
+  static RetEffect MakeOwned(ObjKind o, bool isAllocated = false) {
+    return RetEffect(isAllocated ? OwnedAllocatedSymbol : OwnedSymbol, o);
+  }
+  static RetEffect MakeNotOwned(ObjKind o) {
+    return RetEffect(NotOwnedSymbol, o);
+  }
+  static RetEffect MakeGCNotOwned() {
+    return RetEffect(GCNotOwnedSymbol, ObjC);
+  }
+  static RetEffect MakeARCNotOwned() {
+    return RetEffect(ARCNotOwnedSymbol, ObjC);
+  }
+  static RetEffect MakeNoRet() {
+    return RetEffect(NoRet);
+  }
+
+  void Profile(llvm::FoldingSetNodeID& ID) const {
+    ID.AddInteger((unsigned) K);
+    ID.AddInteger((unsigned) O);
+  }
+};
+
+//===----------------------------------------------------------------------===//
+// Reference-counting logic (typestate + counts).
+//===----------------------------------------------------------------------===//
+
+class RefVal {
+public:
+  enum Kind {
+    Owned = 0, // Owning reference.
+    NotOwned,  // Reference is not owned by still valid (not freed).
+    Released,  // Object has been released.
+    ReturnedOwned, // Returned object passes ownership to caller.
+    ReturnedNotOwned, // Return object does not pass ownership to caller.
+    ERROR_START,
+    ErrorDeallocNotOwned, // -dealloc called on non-owned object.
+    ErrorDeallocGC, // Calling -dealloc with GC enabled.
+    ErrorUseAfterRelease, // Object used after released.
+    ErrorReleaseNotOwned, // Release of an object that was not owned.
+    ERROR_LEAK_START,
+    ErrorLeak,  // A memory leak due to excessive reference counts.
+    ErrorLeakReturned, // A memory leak due to the returning method not having
+                       // the correct naming conventions.
+    ErrorGCLeakReturned,
+    ErrorOverAutorelease,
+    ErrorReturnedNotOwned
+  };
+
+private:
+  Kind kind;
+  RetEffect::ObjKind okind;
+  unsigned Cnt;
+  unsigned ACnt;
+  QualType T;
+
+  RefVal(Kind k, RetEffect::ObjKind o, unsigned cnt, unsigned acnt, QualType t)
+  : kind(k), okind(o), Cnt(cnt), ACnt(acnt), T(t) {}
+
+public:
+  Kind getKind() const { return kind; }
+
+  RetEffect::ObjKind getObjKind() const { return okind; }
+
+  unsigned getCount() const { return Cnt; }
+  unsigned getAutoreleaseCount() const { return ACnt; }
+  unsigned getCombinedCounts() const { return Cnt + ACnt; }
+  void clearCounts() { Cnt = 0; ACnt = 0; }
+  void setCount(unsigned i) { Cnt = i; }
+  void setAutoreleaseCount(unsigned i) { ACnt = i; }
+
+  QualType getType() const { return T; }
+
+  bool isOwned() const {
+    return getKind() == Owned;
+  }
+
+  bool isNotOwned() const {
+    return getKind() == NotOwned;
+  }
+
+  bool isReturnedOwned() const {
+    return getKind() == ReturnedOwned;
+  }
+
+  bool isReturnedNotOwned() const {
+    return getKind() == ReturnedNotOwned;
+  }
+
+  static RefVal makeOwned(RetEffect::ObjKind o, QualType t,
+                          unsigned Count = 1) {
+    return RefVal(Owned, o, Count, 0, t);
+  }
+
+  static RefVal makeNotOwned(RetEffect::ObjKind o, QualType t,
+                             unsigned Count = 0) {
+    return RefVal(NotOwned, o, Count, 0, t);
+  }
+
+  // Comparison, profiling, and pretty-printing.
+
+  bool operator==(const RefVal& X) const {
+    return kind == X.kind && Cnt == X.Cnt && T == X.T && ACnt == X.ACnt;
+  }
+
+  RefVal operator-(size_t i) const {
+    return RefVal(getKind(), getObjKind(), getCount() - i,
+                  getAutoreleaseCount(), getType());
+  }
+
+  RefVal operator+(size_t i) const {
+    return RefVal(getKind(), getObjKind(), getCount() + i,
+                  getAutoreleaseCount(), getType());
+  }
+
+  RefVal operator^(Kind k) const {
+    return RefVal(k, getObjKind(), getCount(), getAutoreleaseCount(),
+                  getType());
+  }
+
+  RefVal autorelease() const {
+    return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount()+1,
+                  getType());
+  }
+
+  void Profile(llvm::FoldingSetNodeID& ID) const {
+    ID.AddInteger((unsigned) kind);
+    ID.AddInteger(Cnt);
+    ID.AddInteger(ACnt);
+    ID.Add(T);
+  }
+
+  void print(raw_ostream &Out) const;
+};
+
+void RefVal::print(raw_ostream &Out) const {
+  if (!T.isNull())
+    Out << "Tracked " << T.getAsString() << '/';
+
+  switch (getKind()) {
+    default: llvm_unreachable("Invalid RefVal kind");
+    case Owned: {
+      Out << "Owned";
+      unsigned cnt = getCount();
+      if (cnt) Out << " (+ " << cnt << ")";
+      break;
+    }
+
+    case NotOwned: {
+      Out << "NotOwned";
+      unsigned cnt = getCount();
+      if (cnt) Out << " (+ " << cnt << ")";
+      break;
+    }
+
+    case ReturnedOwned: {
+      Out << "ReturnedOwned";
+      unsigned cnt = getCount();
+      if (cnt) Out << " (+ " << cnt << ")";
+      break;
+    }
+
+    case ReturnedNotOwned: {
+      Out << "ReturnedNotOwned";
+      unsigned cnt = getCount();
+      if (cnt) Out << " (+ " << cnt << ")";
+      break;
+    }
+
+    case Released:
+      Out << "Released";
+      break;
+
+    case ErrorDeallocGC:
+      Out << "-dealloc (GC)";
+      break;
+
+    case ErrorDeallocNotOwned:
+      Out << "-dealloc (not-owned)";
+      break;
+
+    case ErrorLeak:
+      Out << "Leaked";
+      break;
+
+    case ErrorLeakReturned:
+      Out << "Leaked (Bad naming)";
+      break;
+
+    case ErrorGCLeakReturned:
+      Out << "Leaked (GC-ed at return)";
+      break;
+
+    case ErrorUseAfterRelease:
+      Out << "Use-After-Release [ERROR]";
+      break;
+
+    case ErrorReleaseNotOwned:
+      Out << "Release of Not-Owned [ERROR]";
+      break;
+
+    case RefVal::ErrorOverAutorelease:
+      Out << "Over autoreleased";
+      break;
+
+    case RefVal::ErrorReturnedNotOwned:
+      Out << "Non-owned object returned instead of owned";
+      break;
+  }
+
+  if (ACnt) {
+    Out << " [ARC +" << ACnt << ']';
+  }
+}
+} //end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// RefBindings - State used to track object reference counts.
+//===----------------------------------------------------------------------===//
+
+typedef llvm::ImmutableMap<SymbolRef, RefVal> RefBindings;
+
+namespace clang {
+namespace ento {
+template<>
+struct ProgramStateTrait<RefBindings>
+  : public ProgramStatePartialTrait<RefBindings> {
+  static void *GDMIndex() {
+    static int RefBIndex = 0;
+    return &RefBIndex;
+  }
+};
+}
+}
+
+//===----------------------------------------------------------------------===//
+// Function/Method behavior summaries.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class RetainSummary {
+  /// Args - a map of (index, ArgEffect) pairs, where index
+  ///  specifies the argument (starting from 0).  This can be sparsely
+  ///  populated; arguments with no entry in Args use 'DefaultArgEffect'.
+  ArgEffects Args;
+
+  /// DefaultArgEffect - The default ArgEffect to apply to arguments that
+  ///  do not have an entry in Args.
+  ArgEffect DefaultArgEffect;
+
+  /// Receiver - If this summary applies to an Objective-C message expression,
+  ///  this is the effect applied to the state of the receiver.
+  ArgEffect Receiver;
+
+  /// Ret - The effect on the return value.  Used to indicate if the
+  ///  function/method call returns a new tracked symbol.
+  RetEffect Ret;
+
+public:
+  RetainSummary(ArgEffects A, RetEffect R, ArgEffect defaultEff,
+                ArgEffect ReceiverEff)
+    : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff), Ret(R) {}
+
+  /// getArg - Return the argument effect on the argument specified by
+  ///  idx (starting from 0).
+  ArgEffect getArg(unsigned idx) const {
+    if (const ArgEffect *AE = Args.lookup(idx))
+      return *AE;
+
+    return DefaultArgEffect;
+  }
+  
+  void addArg(ArgEffects::Factory &af, unsigned idx, ArgEffect e) {
+    Args = af.add(Args, idx, e);
+  }
+
+  /// setDefaultArgEffect - Set the default argument effect.
+  void setDefaultArgEffect(ArgEffect E) {
+    DefaultArgEffect = E;
+  }
+
+  /// getRetEffect - Returns the effect on the return value of the call.
+  RetEffect getRetEffect() const { return Ret; }
+
+  /// setRetEffect - Set the effect of the return value of the call.
+  void setRetEffect(RetEffect E) { Ret = E; }
+
+  
+  /// Sets the effect on the receiver of the message.
+  void setReceiverEffect(ArgEffect e) { Receiver = e; }
+  
+  /// getReceiverEffect - Returns the effect on the receiver of the call.
+  ///  This is only meaningful if the summary applies to an ObjCMessageExpr*.
+  ArgEffect getReceiverEffect() const { return Receiver; }
+
+  /// Test if two retain summaries are identical. Note that merely equivalent
+  /// summaries are not necessarily identical (for example, if an explicit 
+  /// argument effect matches the default effect).
+  bool operator==(const RetainSummary &Other) const {
+    return Args == Other.Args && DefaultArgEffect == Other.DefaultArgEffect &&
+           Receiver == Other.Receiver && Ret == Other.Ret;
+  }
+
+  /// Profile this summary for inclusion in a FoldingSet.
+  void Profile(llvm::FoldingSetNodeID& ID) const {
+    ID.Add(Args);
+    ID.Add(DefaultArgEffect);
+    ID.Add(Receiver);
+    ID.Add(Ret);
+  }
+
+  /// A retain summary is simple if it has no ArgEffects other than the default.
+  bool isSimple() const {
+    return Args.isEmpty();
+  }
+};
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Data structures for constructing summaries.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class ObjCSummaryKey {
+  IdentifierInfo* II;
+  Selector S;
+public:
+  ObjCSummaryKey(IdentifierInfo* ii, Selector s)
+    : II(ii), S(s) {}
+
+  ObjCSummaryKey(const ObjCInterfaceDecl *d, Selector s)
+    : II(d ? d->getIdentifier() : 0), S(s) {}
+
+  ObjCSummaryKey(const ObjCInterfaceDecl *d, IdentifierInfo *ii, Selector s)
+    : II(d ? d->getIdentifier() : ii), S(s) {}
+
+  ObjCSummaryKey(Selector s)
+    : II(0), S(s) {}
+
+  IdentifierInfo *getIdentifier() const { return II; }
+  Selector getSelector() const { return S; }
+};
+}
+
+namespace llvm {
+template <> struct DenseMapInfo<ObjCSummaryKey> {
+  static inline ObjCSummaryKey getEmptyKey() {
+    return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getEmptyKey(),
+                          DenseMapInfo<Selector>::getEmptyKey());
+  }
+
+  static inline ObjCSummaryKey getTombstoneKey() {
+    return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getTombstoneKey(),
+                          DenseMapInfo<Selector>::getTombstoneKey());
+  }
+
+  static unsigned getHashValue(const ObjCSummaryKey &V) {
+    return (DenseMapInfo<IdentifierInfo*>::getHashValue(V.getIdentifier())
+            & 0x88888888)
+        | (DenseMapInfo<Selector>::getHashValue(V.getSelector())
+            & 0x55555555);
+  }
+
+  static bool isEqual(const ObjCSummaryKey& LHS, const ObjCSummaryKey& RHS) {
+    return DenseMapInfo<IdentifierInfo*>::isEqual(LHS.getIdentifier(),
+                                                  RHS.getIdentifier()) &&
+           DenseMapInfo<Selector>::isEqual(LHS.getSelector(),
+                                           RHS.getSelector());
+  }
+
+};
+template <>
+struct isPodLike<ObjCSummaryKey> { static const bool value = true; };
+} // end llvm namespace
+
+namespace {
+class ObjCSummaryCache {
+  typedef llvm::DenseMap<ObjCSummaryKey, const RetainSummary *> MapTy;
+  MapTy M;
+public:
+  ObjCSummaryCache() {}
+
+  const RetainSummary * find(const ObjCInterfaceDecl *D, IdentifierInfo *ClsName,
+                Selector S) {
+    // Lookup the method using the decl for the class @interface.  If we
+    // have no decl, lookup using the class name.
+    return D ? find(D, S) : find(ClsName, S);
+  }
+
+  const RetainSummary * find(const ObjCInterfaceDecl *D, Selector S) {
+    // Do a lookup with the (D,S) pair.  If we find a match return
+    // the iterator.
+    ObjCSummaryKey K(D, S);
+    MapTy::iterator I = M.find(K);
+
+    if (I != M.end() || !D)
+      return I->second;
+
+    // Walk the super chain.  If we find a hit with a parent, we'll end
+    // up returning that summary.  We actually allow that key (null,S), as
+    // we cache summaries for the null ObjCInterfaceDecl* to allow us to
+    // generate initial summaries without having to worry about NSObject
+    // being declared.
+    // FIXME: We may change this at some point.
+    for (ObjCInterfaceDecl *C=D->getSuperClass() ;; C=C->getSuperClass()) {
+      if ((I = M.find(ObjCSummaryKey(C, S))) != M.end())
+        break;
+
+      if (!C)
+        return NULL;
+    }
+
+    // Cache the summary with original key to make the next lookup faster
+    // and return the iterator.
+    const RetainSummary *Summ = I->second;
+    M[K] = Summ;
+    return Summ;
+  }
+
+  const RetainSummary *find(IdentifierInfo* II, Selector S) {
+    // FIXME: Class method lookup.  Right now we dont' have a good way
+    // of going between IdentifierInfo* and the class hierarchy.
+    MapTy::iterator I = M.find(ObjCSummaryKey(II, S));
+
+    if (I == M.end())
+      I = M.find(ObjCSummaryKey(S));
+
+    return I == M.end() ? NULL : I->second;
+  }
+
+  const RetainSummary *& operator[](ObjCSummaryKey K) {
+    return M[K];
+  }
+
+  const RetainSummary *& operator[](Selector S) {
+    return M[ ObjCSummaryKey(S) ];
+  }
+};
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Data structures for managing collections of summaries.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class RetainSummaryManager {
+
+  //==-----------------------------------------------------------------==//
+  //  Typedefs.
+  //==-----------------------------------------------------------------==//
+
+  typedef llvm::DenseMap<const FunctionDecl*, const RetainSummary *>
+          FuncSummariesTy;
+
+  typedef ObjCSummaryCache ObjCMethodSummariesTy;
+
+  typedef llvm::FoldingSetNodeWrapper<RetainSummary> CachedSummaryNode;
+
+  //==-----------------------------------------------------------------==//
+  //  Data.
+  //==-----------------------------------------------------------------==//
+
+  /// Ctx - The ASTContext object for the analyzed ASTs.
+  ASTContext &Ctx;
+
+  /// GCEnabled - Records whether or not the analyzed code runs in GC mode.
+  const bool GCEnabled;
+
+  /// Records whether or not the analyzed code runs in ARC mode.
+  const bool ARCEnabled;
+
+  /// FuncSummaries - A map from FunctionDecls to summaries.
+  FuncSummariesTy FuncSummaries;
+
+  /// ObjCClassMethodSummaries - A map from selectors (for instance methods)
+  ///  to summaries.
+  ObjCMethodSummariesTy ObjCClassMethodSummaries;
+
+  /// ObjCMethodSummaries - A map from selectors to summaries.
+  ObjCMethodSummariesTy ObjCMethodSummaries;
+
+  /// BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
+  ///  and all other data used by the checker.
+  llvm::BumpPtrAllocator BPAlloc;
+
+  /// AF - A factory for ArgEffects objects.
+  ArgEffects::Factory AF;
+
+  /// ScratchArgs - A holding buffer for construct ArgEffects.
+  ArgEffects ScratchArgs; 
+
+  /// ObjCAllocRetE - Default return effect for methods returning Objective-C
+  ///  objects.
+  RetEffect ObjCAllocRetE;
+
+  /// ObjCInitRetE - Default return effect for init methods returning
+  ///   Objective-C objects.
+  RetEffect ObjCInitRetE;
+
+  /// SimpleSummaries - Used for uniquing summaries that don't have special
+  /// effects.
+  llvm::FoldingSet<CachedSummaryNode> SimpleSummaries;
+
+  //==-----------------------------------------------------------------==//
+  //  Methods.
+  //==-----------------------------------------------------------------==//
+
+  /// getArgEffects - Returns a persistent ArgEffects object based on the
+  ///  data in ScratchArgs.
+  ArgEffects getArgEffects();
+
+  enum UnaryFuncKind { cfretain, cfrelease, cfmakecollectable };
+
+public:
+  RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
+  
+  const RetainSummary *getUnarySummary(const FunctionType* FT,
+                                       UnaryFuncKind func);
+
+  const RetainSummary *getCFSummaryCreateRule(const FunctionDecl *FD);
+  const RetainSummary *getCFSummaryGetRule(const FunctionDecl *FD);
+  const RetainSummary *getCFCreateGetRuleSummary(const FunctionDecl *FD);
+
+  const RetainSummary *getPersistentSummary(const RetainSummary &OldSumm);
+
+  const RetainSummary *getPersistentSummary(RetEffect RetEff,
+                                            ArgEffect ReceiverEff = DoNothing,
+                                            ArgEffect DefaultEff = MayEscape) {
+    RetainSummary Summ(getArgEffects(), RetEff, DefaultEff, ReceiverEff);
+    return getPersistentSummary(Summ);
+  }
+
+  const RetainSummary *getDefaultSummary() {
+    return getPersistentSummary(RetEffect::MakeNoRet(),
+                                DoNothing, MayEscape);
+  }
+
+  const RetainSummary *getPersistentStopSummary() {
+    return getPersistentSummary(RetEffect::MakeNoRet(),
+                                StopTracking, StopTracking);
+  }
+
+  void InitializeClassMethodSummaries();
+  void InitializeMethodSummaries();
+private:
+  void addNSObjectClsMethSummary(Selector S, const RetainSummary *Summ) {
+    ObjCClassMethodSummaries[S] = Summ;
+  }
+
+  void addNSObjectMethSummary(Selector S, const RetainSummary *Summ) {
+    ObjCMethodSummaries[S] = Summ;
+  }
+
+  void addClassMethSummary(const char* Cls, const char* name,
+                           const RetainSummary *Summ, bool isNullary = true) {
+    IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
+    Selector S = isNullary ? GetNullarySelector(name, Ctx) 
+                           : GetUnarySelector(name, Ctx);
+    ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)]  = Summ;
+  }
+
+  void addInstMethSummary(const char* Cls, const char* nullaryName,
+                          const RetainSummary *Summ) {
+    IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
+    Selector S = GetNullarySelector(nullaryName, Ctx);
+    ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)]  = Summ;
+  }
+
+  Selector generateSelector(va_list argp) {
+    SmallVector<IdentifierInfo*, 10> II;
+
+    while (const char* s = va_arg(argp, const char*))
+      II.push_back(&Ctx.Idents.get(s));
+
+    return Ctx.Selectors.getSelector(II.size(), &II[0]);
+  }
+
+  void addMethodSummary(IdentifierInfo *ClsII, ObjCMethodSummariesTy& Summaries,
+                        const RetainSummary * Summ, va_list argp) {
+    Selector S = generateSelector(argp);
+    Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
+  }
+
+  void addInstMethSummary(const char* Cls, const RetainSummary * Summ, ...) {
+    va_list argp;
+    va_start(argp, Summ);
+    addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, argp);
+    va_end(argp);
+  }
+
+  void addClsMethSummary(const char* Cls, const RetainSummary * Summ, ...) {
+    va_list argp;
+    va_start(argp, Summ);
+    addMethodSummary(&Ctx.Idents.get(Cls),ObjCClassMethodSummaries, Summ, argp);
+    va_end(argp);
+  }
+
+  void addClsMethSummary(IdentifierInfo *II, const RetainSummary * Summ, ...) {
+    va_list argp;
+    va_start(argp, Summ);
+    addMethodSummary(II, ObjCClassMethodSummaries, Summ, argp);
+    va_end(argp);
+  }
+
+public:
+
+  RetainSummaryManager(ASTContext &ctx, bool gcenabled, bool usesARC)
+   : Ctx(ctx),
+     GCEnabled(gcenabled),
+     ARCEnabled(usesARC),
+     AF(BPAlloc), ScratchArgs(AF.getEmptyMap()),
+     ObjCAllocRetE(gcenabled
+                    ? RetEffect::MakeGCNotOwned()
+                    : (usesARC ? RetEffect::MakeARCNotOwned()
+                               : RetEffect::MakeOwned(RetEffect::ObjC, true))),
+     ObjCInitRetE(gcenabled 
+                    ? RetEffect::MakeGCNotOwned()
+                    : (usesARC ? RetEffect::MakeARCNotOwned()
+                               : RetEffect::MakeOwnedWhenTrackedReceiver())) {
+    InitializeClassMethodSummaries();
+    InitializeMethodSummaries();
+  }
+
+  const RetainSummary *getSummary(const FunctionDecl *FD);
+
+  const RetainSummary *getMethodSummary(Selector S, IdentifierInfo *ClsName,
+                                        const ObjCInterfaceDecl *ID,
+                                        const ObjCMethodDecl *MD,
+                                        QualType RetTy,
+                                        ObjCMethodSummariesTy &CachedSummaries);
+
+  const RetainSummary *getInstanceMethodSummary(const ObjCMessage &msg,
+                                                ProgramStateRef state,
+                                                const LocationContext *LC);
+
+  const RetainSummary *getInstanceMethodSummary(const ObjCMessage &msg,
+                                                const ObjCInterfaceDecl *ID) {
+    return getMethodSummary(msg.getSelector(), 0, ID, msg.getMethodDecl(),
+                            msg.getType(Ctx), ObjCMethodSummaries);
+  }
+
+  const RetainSummary *getClassMethodSummary(const ObjCMessage &msg) {
+    const ObjCInterfaceDecl *Class = 0;
+    if (!msg.isInstanceMessage())
+      Class = msg.getReceiverInterface();
+
+    return getMethodSummary(msg.getSelector(), Class->getIdentifier(),
+                            Class, msg.getMethodDecl(), msg.getType(Ctx),
+                            ObjCClassMethodSummaries);
+  }
+
+  /// getMethodSummary - This version of getMethodSummary is used to query
+  ///  the summary for the current method being analyzed.
+  const RetainSummary *getMethodSummary(const ObjCMethodDecl *MD) {
+    // FIXME: Eventually this should be unneeded.
+    const ObjCInterfaceDecl *ID = MD->getClassInterface();
+    Selector S = MD->getSelector();
+    IdentifierInfo *ClsName = ID->getIdentifier();
+    QualType ResultTy = MD->getResultType();
+
+    ObjCMethodSummariesTy *CachedSummaries;
+    if (MD->isInstanceMethod())
+      CachedSummaries = &ObjCMethodSummaries;
+    else
+      CachedSummaries = &ObjCClassMethodSummaries;
+
+    return getMethodSummary(S, ClsName, ID, MD, ResultTy, *CachedSummaries);
+  }
+
+  const RetainSummary *getStandardMethodSummary(const ObjCMethodDecl *MD,
+                                              Selector S, QualType RetTy);
+
+  void updateSummaryFromAnnotations(const RetainSummary *&Summ,
+                                    const ObjCMethodDecl *MD);
+
+  void updateSummaryFromAnnotations(const RetainSummary *&Summ,
+                                    const FunctionDecl *FD);
+
+  bool isGCEnabled() const { return GCEnabled; }
+
+  bool isARCEnabled() const { return ARCEnabled; }
+  
+  bool isARCorGCEnabled() const { return GCEnabled || ARCEnabled; }
+};
+
+// Used to avoid allocating long-term (BPAlloc'd) memory for default retain
+// summaries. If a function or method looks like it has a default summary, but
+// it has annotations, the annotations are added to the stack-based template
+// and then copied into managed memory.
+class RetainSummaryTemplate {
+  RetainSummaryManager &Manager;
+  const RetainSummary *&RealSummary;
+  RetainSummary ScratchSummary;
+  bool Accessed;
+public:
+  RetainSummaryTemplate(const RetainSummary *&real, const RetainSummary &base, 
+                        RetainSummaryManager &mgr)
+  : Manager(mgr), RealSummary(real), ScratchSummary(real ? *real : base),
+    Accessed(false) {}
+
+  ~RetainSummaryTemplate() {
+    if (Accessed)
+      RealSummary = Manager.getPersistentSummary(ScratchSummary);
+  }
+
+  RetainSummary &operator*() {
+    Accessed = true;
+    return ScratchSummary;
+  }
+
+  RetainSummary *operator->() {
+    Accessed = true;
+    return &ScratchSummary;
+  }
+};
+
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Implementation of checker data structures.
+//===----------------------------------------------------------------------===//
+
+ArgEffects RetainSummaryManager::getArgEffects() {
+  ArgEffects AE = ScratchArgs;
+  ScratchArgs = AF.getEmptyMap();
+  return AE;
+}
+
+const RetainSummary *
+RetainSummaryManager::getPersistentSummary(const RetainSummary &OldSumm) {
+  // Unique "simple" summaries -- those without ArgEffects.
+  if (OldSumm.isSimple()) {
+    llvm::FoldingSetNodeID ID;
+    OldSumm.Profile(ID);
+
+    void *Pos;
+    CachedSummaryNode *N = SimpleSummaries.FindNodeOrInsertPos(ID, Pos);
+
+    if (!N) {
+      N = (CachedSummaryNode *) BPAlloc.Allocate<CachedSummaryNode>();
+      new (N) CachedSummaryNode(OldSumm);
+      SimpleSummaries.InsertNode(N, Pos);
+    }
+
+    return &N->getValue();
+  }
+
+  RetainSummary *Summ = (RetainSummary *) BPAlloc.Allocate<RetainSummary>();
+  new (Summ) RetainSummary(OldSumm);
+  return Summ;
+}
+
+//===----------------------------------------------------------------------===//
+// Summary creation for functions (largely uses of Core Foundation).
+//===----------------------------------------------------------------------===//
+
+static bool isRetain(const FunctionDecl *FD, StringRef FName) {
+  return FName.endswith("Retain");
+}
+
+static bool isRelease(const FunctionDecl *FD, StringRef FName) {
+  return FName.endswith("Release");
+}
+
+static bool isMakeCollectable(const FunctionDecl *FD, StringRef FName) {
+  // FIXME: Remove FunctionDecl parameter.
+  // FIXME: Is it really okay if MakeCollectable isn't a suffix?
+  return FName.find("MakeCollectable") != StringRef::npos;
+}
+
+const RetainSummary * RetainSummaryManager::getSummary(const FunctionDecl *FD) {
+  // Look up a summary in our cache of FunctionDecls -> Summaries.
+  FuncSummariesTy::iterator I = FuncSummaries.find(FD);
+  if (I != FuncSummaries.end())
+    return I->second;
+
+  // No summary?  Generate one.
+  const RetainSummary *S = 0;
+
+  do {
+    // We generate "stop" summaries for implicitly defined functions.
+    if (FD->isImplicit()) {
+      S = getPersistentStopSummary();
+      break;
+    }
+    // For C++ methods, generate an implicit "stop" summary as well.  We
+    // can relax this once we have a clear policy for C++ methods and
+    // ownership attributes.
+    if (isa<CXXMethodDecl>(FD)) {
+      S = getPersistentStopSummary();
+      break;
+    }
+
+    // [PR 3337] Use 'getAs<FunctionType>' to strip away any typedefs on the
+    // function's type.
+    const FunctionType* FT = FD->getType()->getAs<FunctionType>();
+    const IdentifierInfo *II = FD->getIdentifier();
+    if (!II)
+      break;
+
+    StringRef FName = II->getName();
+
+    // Strip away preceding '_'.  Doing this here will effect all the checks
+    // down below.
+    FName = FName.substr(FName.find_first_not_of('_'));
+
+    // Inspect the result type.
+    QualType RetTy = FT->getResultType();
+
+    // FIXME: This should all be refactored into a chain of "summary lookup"
+    //  filters.
+    assert(ScratchArgs.isEmpty());
+
+    if (FName == "pthread_create") {
+      // Part of: <rdar://problem/7299394>.  This will be addressed
+      // better with IPA.
+      S = getPersistentStopSummary();
+    } else if (FName == "NSMakeCollectable") {
+      // Handle: id NSMakeCollectable(CFTypeRef)
+      S = (RetTy->isObjCIdType())
+          ? getUnarySummary(FT, cfmakecollectable)
+          : getPersistentStopSummary();
+    } else if (FName == "IOBSDNameMatching" ||
+               FName == "IOServiceMatching" ||
+               FName == "IOServiceNameMatching" ||
+               FName == "IORegistryEntryIDMatching" ||
+               FName == "IOOpenFirmwarePathMatching") {
+      // Part of <rdar://problem/6961230>. (IOKit)
+      // This should be addressed using a API table.
+      S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
+                               DoNothing, DoNothing);
+    } else if (FName == "IOServiceGetMatchingService" ||
+               FName == "IOServiceGetMatchingServices") {
+      // FIXES: <rdar://problem/6326900>
+      // This should be addressed using a API table.  This strcmp is also
+      // a little gross, but there is no need to super optimize here.
+      ScratchArgs = AF.add(ScratchArgs, 1, DecRef);
+      S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
+    } else if (FName == "IOServiceAddNotification" ||
+               FName == "IOServiceAddMatchingNotification") {
+      // Part of <rdar://problem/6961230>. (IOKit)
+      // This should be addressed using a API table.
+      ScratchArgs = AF.add(ScratchArgs, 2, DecRef);
+      S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
+    } else if (FName == "CVPixelBufferCreateWithBytes") {
+      // FIXES: <rdar://problem/7283567>
+      // 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);
+    } else if (FName == "CGBitmapContextCreateWithData") {
+      // 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);
+    } else if (FName == "CVPixelBufferCreateWithPlanarBytes") {
+      // FIXES: <rdar://problem/7283567>
+      // Eventually this can be improved by recognizing that the pixel
+      // buffer passed to CVPixelBufferCreateWithPlanarBytes is released
+      // via a callback and doing full IPA to make sure this is done
+      // correctly.
+      ScratchArgs = AF.add(ScratchArgs, 12, StopTracking);
+      S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
+    } else if (FName == "dispatch_set_context") {
+      // <rdar://problem/11059275> - The analyzer currently doesn't have
+      // a good way to reason about the finalizer function for libdispatch.
+      // If we pass a context object that is memory managed, stop tracking it.
+      // FIXME: this hack should possibly go away once we can handle
+      // libdispatch finalizers.
+      ScratchArgs = AF.add(ScratchArgs, 1, StopTracking);
+      S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
+    } else if (FName.startswith("NS") &&
+                (FName.find("Insert") != StringRef::npos)) {
+      // Whitelist NSXXInsertXX, for example NSMapInsertIfAbsent, since they can
+      // be deallocated by NSMapRemove. (radar://11152419)
+      ScratchArgs = AF.add(ScratchArgs, 1, StopTracking);
+      ScratchArgs = AF.add(ScratchArgs, 2, StopTracking);
+      S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
+    }
+
+    // Did we get a summary?
+    if (S)
+      break;
+
+    // Enable this code once the semantics of NSDeallocateObject are resolved
+    // for GC.  <rdar://problem/6619988>
+#if 0
+    // Handle: NSDeallocateObject(id anObject);
+    // This method does allow 'nil' (although we don't check it now).
+    if (strcmp(FName, "NSDeallocateObject") == 0) {
+      return RetTy == Ctx.VoidTy
+        ? getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, Dealloc)
+        : getPersistentStopSummary();
+    }
+#endif
+
+    if (RetTy->isPointerType()) {
+      // For CoreFoundation ('CF') types.
+      if (cocoa::isRefType(RetTy, "CF", FName)) {
+        if (isRetain(FD, FName))
+          S = getUnarySummary(FT, cfretain);
+        else if (isMakeCollectable(FD, FName))
+          S = getUnarySummary(FT, cfmakecollectable);
+        else
+          S = getCFCreateGetRuleSummary(FD);
+
+        break;
+      }
+
+      // For CoreGraphics ('CG') types.
+      if (cocoa::isRefType(RetTy, "CG", FName)) {
+        if (isRetain(FD, FName))
+          S = getUnarySummary(FT, cfretain);
+        else
+          S = getCFCreateGetRuleSummary(FD);
+
+        break;
+      }
+
+      // For the Disk Arbitration API (DiskArbitration/DADisk.h)
+      if (cocoa::isRefType(RetTy, "DADisk") ||
+          cocoa::isRefType(RetTy, "DADissenter") ||
+          cocoa::isRefType(RetTy, "DASessionRef")) {
+        S = getCFCreateGetRuleSummary(FD);
+        break;
+      }
+
+      break;
+    }
+
+    // Check for release functions, the only kind of functions that we care
+    // about that don't return a pointer type.
+    if (FName[0] == 'C' && (FName[1] == 'F' || FName[1] == 'G')) {
+      // Test for 'CGCF'.
+      FName = FName.substr(FName.startswith("CGCF") ? 4 : 2);
+
+      if (isRelease(FD, FName))
+        S = getUnarySummary(FT, cfrelease);
+      else {
+        assert (ScratchArgs.isEmpty());
+        // Remaining CoreFoundation and CoreGraphics functions.
+        // We use to assume that they all strictly followed the ownership idiom
+        // and that ownership cannot be transferred.  While this is technically
+        // correct, many methods allow a tracked object to escape.  For example:
+        //
+        //   CFMutableDictionaryRef x = CFDictionaryCreateMutable(...);
+        //   CFDictionaryAddValue(y, key, x);
+        //   CFRelease(x);
+        //   ... it is okay to use 'x' since 'y' has a reference to it
+        //
+        // We handle this and similar cases with the follow heuristic.  If the
+        // function name contains "InsertValue", "SetValue", "AddValue",
+        // "AppendValue", or "SetAttribute", then we assume that arguments may
+        // "escape."  This means that something else holds on to the object,
+        // allowing it be used even after its local retain count drops to 0.
+        ArgEffect E = (StrInStrNoCase(FName, "InsertValue") != StringRef::npos||
+                       StrInStrNoCase(FName, "AddValue") != StringRef::npos ||
+                       StrInStrNoCase(FName, "SetValue") != StringRef::npos ||
+                       StrInStrNoCase(FName, "AppendValue") != StringRef::npos||
+                       StrInStrNoCase(FName, "SetAttribute") != StringRef::npos)
+                      ? MayEscape : DoNothing;
+
+        S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, E);
+      }
+    }
+  }
+  while (0);
+
+  // Annotations override defaults.
+  updateSummaryFromAnnotations(S, FD);
+
+  FuncSummaries[FD] = S;
+  return S;
+}
+
+const RetainSummary *
+RetainSummaryManager::getCFCreateGetRuleSummary(const FunctionDecl *FD) {
+  if (coreFoundation::followsCreateRule(FD))
+    return getCFSummaryCreateRule(FD);
+
+  return getCFSummaryGetRule(FD);
+}
+
+const RetainSummary *
+RetainSummaryManager::getUnarySummary(const FunctionType* FT,
+                                      UnaryFuncKind func) {
+
+  // Sanity check that this is *really* a unary function.  This can
+  // happen if people do weird things.
+  const FunctionProtoType* FTP = dyn_cast<FunctionProtoType>(FT);
+  if (!FTP || FTP->getNumArgs() != 1)
+    return getPersistentStopSummary();
+
+  assert (ScratchArgs.isEmpty());
+
+  ArgEffect Effect;
+  switch (func) {
+    case cfretain: Effect = IncRef; break;
+    case cfrelease: Effect = DecRef; break;
+    case cfmakecollectable: Effect = MakeCollectable; break;
+  }
+
+  ScratchArgs = AF.add(ScratchArgs, 0, Effect);
+  return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
+}
+
+const RetainSummary * 
+RetainSummaryManager::getCFSummaryCreateRule(const FunctionDecl *FD) {
+  assert (ScratchArgs.isEmpty());
+
+  return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true));
+}
+
+const RetainSummary * 
+RetainSummaryManager::getCFSummaryGetRule(const FunctionDecl *FD) {
+  assert (ScratchArgs.isEmpty());
+  return getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::CF),
+                              DoNothing, DoNothing);
+}
+
+//===----------------------------------------------------------------------===//
+// Summary creation for Selectors.
+//===----------------------------------------------------------------------===//
+
+void
+RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
+                                                   const FunctionDecl *FD) {
+  if (!FD)
+    return;
+
+  RetainSummaryTemplate Template(Summ, *getDefaultSummary(), *this);
+
+  // Effects on the parameters.
+  unsigned parm_idx = 0;
+  for (FunctionDecl::param_const_iterator pi = FD->param_begin(), 
+         pe = FD->param_end(); pi != pe; ++pi, ++parm_idx) {
+    const ParmVarDecl *pd = *pi;
+    if (pd->getAttr<NSConsumedAttr>()) {
+      if (!GCEnabled) {
+        Template->addArg(AF, parm_idx, DecRef);      
+      }
+    } else if (pd->getAttr<CFConsumedAttr>()) {
+      Template->addArg(AF, parm_idx, DecRef);      
+    }   
+  }
+  
+  QualType RetTy = FD->getResultType();
+
+  // Determine if there is a special return effect for this method.
+  if (cocoa::isCocoaObjectRef(RetTy)) {
+    if (FD->getAttr<NSReturnsRetainedAttr>()) {
+      Template->setRetEffect(ObjCAllocRetE);
+    }
+    else if (FD->getAttr<CFReturnsRetainedAttr>()) {
+      Template->setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
+    }
+    else if (FD->getAttr<NSReturnsNotRetainedAttr>()) {
+      Template->setRetEffect(RetEffect::MakeNotOwned(RetEffect::ObjC));
+    }
+    else if (FD->getAttr<CFReturnsNotRetainedAttr>()) {
+      Template->setRetEffect(RetEffect::MakeNotOwned(RetEffect::CF));
+    }
+  } else if (RetTy->getAs<PointerType>()) {
+    if (FD->getAttr<CFReturnsRetainedAttr>()) {
+      Template->setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
+    }
+    else if (FD->getAttr<CFReturnsNotRetainedAttr>()) {
+      Template->setRetEffect(RetEffect::MakeNotOwned(RetEffect::CF));
+    }
+  }
+}
+
+void
+RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
+                                                   const ObjCMethodDecl *MD) {
+  if (!MD)
+    return;
+
+  RetainSummaryTemplate Template(Summ, *getDefaultSummary(), *this);
+  bool isTrackedLoc = false;
+
+  // Effects on the receiver.
+  if (MD->getAttr<NSConsumesSelfAttr>()) {
+    if (!GCEnabled)
+      Template->setReceiverEffect(DecRefMsg);      
+  }
+  
+  // Effects on the parameters.
+  unsigned parm_idx = 0;
+  for (ObjCMethodDecl::param_const_iterator
+         pi=MD->param_begin(), pe=MD->param_end();
+       pi != pe; ++pi, ++parm_idx) {
+    const ParmVarDecl *pd = *pi;
+    if (pd->getAttr<NSConsumedAttr>()) {
+      if (!GCEnabled)
+        Template->addArg(AF, parm_idx, DecRef);      
+    }
+    else if(pd->getAttr<CFConsumedAttr>()) {
+      Template->addArg(AF, parm_idx, DecRef);      
+    }   
+  }
+  
+  // Determine if there is a special return effect for this method.
+  if (cocoa::isCocoaObjectRef(MD->getResultType())) {
+    if (MD->getAttr<NSReturnsRetainedAttr>()) {
+      Template->setRetEffect(ObjCAllocRetE);
+      return;
+    }
+    if (MD->getAttr<NSReturnsNotRetainedAttr>()) {
+      Template->setRetEffect(RetEffect::MakeNotOwned(RetEffect::ObjC));
+      return;
+    }
+
+    isTrackedLoc = true;
+  } else {
+    isTrackedLoc = MD->getResultType()->getAs<PointerType>() != NULL;
+  }
+
+  if (isTrackedLoc) {
+    if (MD->getAttr<CFReturnsRetainedAttr>())
+      Template->setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
+    else if (MD->getAttr<CFReturnsNotRetainedAttr>())
+      Template->setRetEffect(RetEffect::MakeNotOwned(RetEffect::CF));
+  }
+}
+
+const RetainSummary *
+RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,
+                                               Selector S, QualType RetTy) {
+
+  if (MD) {
+    // Scan the method decl for 'void*' arguments.  These should be treated
+    // as 'StopTracking' because they are often used with delegates.
+    // Delegates are a frequent form of false positives with the retain
+    // count checker.
+    unsigned i = 0;
+    for (ObjCMethodDecl::param_const_iterator I = MD->param_begin(),
+         E = MD->param_end(); I != E; ++I, ++i)
+      if (const ParmVarDecl *PD = *I) {
+        QualType Ty = Ctx.getCanonicalType(PD->getType());
+        if (Ty.getLocalUnqualifiedType() == Ctx.VoidPtrTy)
+          ScratchArgs = AF.add(ScratchArgs, i, StopTracking);
+      }
+  }
+
+  // Any special effects?
+  ArgEffect ReceiverEff = DoNothing;
+  RetEffect ResultEff = RetEffect::MakeNoRet();
+
+  // Check the method family, and apply any default annotations.
+  switch (MD ? MD->getMethodFamily() : S.getMethodFamily()) {
+    case OMF_None:
+    case OMF_performSelector:
+      // Assume all Objective-C methods follow Cocoa Memory Management rules.
+      // FIXME: Does the non-threaded performSelector family really belong here?
+      // The selector could be, say, @selector(copy).
+      if (cocoa::isCocoaObjectRef(RetTy))
+        ResultEff = RetEffect::MakeNotOwned(RetEffect::ObjC);
+      else if (coreFoundation::isCFObjectRef(RetTy)) {
+        // ObjCMethodDecl currently doesn't consider CF objects as valid return 
+        // values for alloc, new, copy, or mutableCopy, so we have to
+        // double-check with the selector. This is ugly, but there aren't that
+        // many Objective-C methods that return CF objects, right?
+        if (MD) {
+          switch (S.getMethodFamily()) {
+          case OMF_alloc:
+          case OMF_new:
+          case OMF_copy:
+          case OMF_mutableCopy:
+            ResultEff = RetEffect::MakeOwned(RetEffect::CF, true);
+            break;
+          default:
+            ResultEff = RetEffect::MakeNotOwned(RetEffect::CF);        
+            break;
+          }
+        } else {
+          ResultEff = RetEffect::MakeNotOwned(RetEffect::CF);        
+        }
+      }
+      break;
+    case OMF_init:
+      ResultEff = ObjCInitRetE;
+      ReceiverEff = DecRefMsg;
+      break;
+    case OMF_alloc:
+    case OMF_new:
+    case OMF_copy:
+    case OMF_mutableCopy:
+      if (cocoa::isCocoaObjectRef(RetTy))
+        ResultEff = ObjCAllocRetE;
+      else if (coreFoundation::isCFObjectRef(RetTy))
+        ResultEff = RetEffect::MakeOwned(RetEffect::CF, true);
+      break;
+    case OMF_autorelease:
+      ReceiverEff = Autorelease;
+      break;
+    case OMF_retain:
+      ReceiverEff = IncRefMsg;
+      break;
+    case OMF_release:
+      ReceiverEff = DecRefMsg;
+      break;
+    case OMF_dealloc:
+      ReceiverEff = Dealloc;
+      break;
+    case OMF_self:
+      // -self is handled specially by the ExprEngine to propagate the receiver.
+      break;
+    case OMF_retainCount:
+    case OMF_finalize:
+      // These methods don't return objects.
+      break;
+  }
+
+  // If one of the arguments in the selector has the keyword 'delegate' we
+  // should stop tracking the reference count for the receiver.  This is
+  // because the reference count is quite possibly handled by a delegate
+  // method.
+  if (S.isKeywordSelector()) {
+    const std::string &str = S.getAsString();
+    assert(!str.empty());
+    if (StrInStrNoCase(str, "delegate:") != StringRef::npos)
+      ReceiverEff = StopTracking;
+  }
+
+  if (ScratchArgs.isEmpty() && ReceiverEff == DoNothing &&
+      ResultEff.getKind() == RetEffect::NoRet)
+    return getDefaultSummary();
+
+  return getPersistentSummary(ResultEff, ReceiverEff, MayEscape);
+}
+
+const RetainSummary *
+RetainSummaryManager::getInstanceMethodSummary(const ObjCMessage &msg,
+                                               ProgramStateRef state,
+                                               const LocationContext *LC) {
+
+  // We need the type-information of the tracked receiver object
+  // Retrieve it from the state.
+  const Expr *Receiver = msg.getInstanceReceiver();
+  const ObjCInterfaceDecl *ID = 0;
+
+  // FIXME: Is this really working as expected?  There are cases where
+  //  we just use the 'ID' from the message expression.
+  SVal receiverV;
+
+  if (Receiver) {
+    receiverV = state->getSValAsScalarOrLoc(Receiver, LC);
+
+    // FIXME: Eventually replace the use of state->get<RefBindings> with
+    // a generic API for reasoning about the Objective-C types of symbolic
+    // objects.
+    if (SymbolRef Sym = receiverV.getAsLocSymbol())
+      if (const RefVal *T = state->get<RefBindings>(Sym))
+        if (const ObjCObjectPointerType* PT =
+            T->getType()->getAs<ObjCObjectPointerType>())
+          ID = PT->getInterfaceDecl();
+
+    // FIXME: this is a hack.  This may or may not be the actual method
+    //  that is called.
+    if (!ID) {
+      if (const ObjCObjectPointerType *PT =
+          Receiver->getType()->getAs<ObjCObjectPointerType>())
+        ID = PT->getInterfaceDecl();
+    }
+  } else {
+    // FIXME: Hack for 'super'.
+    ID = msg.getReceiverInterface();
+  }
+
+  // FIXME: The receiver could be a reference to a class, meaning that
+  //  we should use the class method.
+  return getInstanceMethodSummary(msg, ID);
+}
+
+const RetainSummary *
+RetainSummaryManager::getMethodSummary(Selector S, IdentifierInfo *ClsName,
+                                       const ObjCInterfaceDecl *ID,
+                                       const ObjCMethodDecl *MD, QualType RetTy,
+                                       ObjCMethodSummariesTy &CachedSummaries) {
+
+  // Look up a summary in our summary cache.
+  const RetainSummary *Summ = CachedSummaries.find(ID, ClsName, S);
+
+  if (!Summ) {
+    Summ = getStandardMethodSummary(MD, S, RetTy);
+
+    // Annotations override defaults.
+    updateSummaryFromAnnotations(Summ, MD);
+
+    // Memoize the summary.
+    CachedSummaries[ObjCSummaryKey(ID, ClsName, S)] = Summ;
+  }
+
+  return Summ;
+}
+
+void RetainSummaryManager::InitializeClassMethodSummaries() {
+  assert(ScratchArgs.isEmpty());
+  // Create the [NSAssertionHandler currentHander] summary.
+  addClassMethSummary("NSAssertionHandler", "currentHandler",
+                getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::ObjC)));
+
+  // Create the [NSAutoreleasePool addObject:] summary.
+  ScratchArgs = AF.add(ScratchArgs, 0, Autorelease);
+  addClassMethSummary("NSAutoreleasePool", "addObject",
+                      getPersistentSummary(RetEffect::MakeNoRet(),
+                                           DoNothing, Autorelease));
+
+  // Create the summaries for [NSObject performSelector...].  We treat
+  // these as 'stop tracking' for the arguments because they are often
+  // used for delegates that can release the object.  When we have better
+  // inter-procedural analysis we can potentially do something better.  This
+  // workaround is to remove false positives.
+  const RetainSummary *Summ =
+    getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, StopTracking);
+  IdentifierInfo *NSObjectII = &Ctx.Idents.get("NSObject");
+  addClsMethSummary(NSObjectII, Summ, "performSelector", "withObject",
+                    "afterDelay", NULL);
+  addClsMethSummary(NSObjectII, Summ, "performSelector", "withObject",
+                    "afterDelay", "inModes", NULL);
+  addClsMethSummary(NSObjectII, Summ, "performSelectorOnMainThread",
+                    "withObject", "waitUntilDone", NULL);
+  addClsMethSummary(NSObjectII, Summ, "performSelectorOnMainThread",
+                    "withObject", "waitUntilDone", "modes", NULL);
+  addClsMethSummary(NSObjectII, Summ, "performSelector", "onThread",
+                    "withObject", "waitUntilDone", NULL);
+  addClsMethSummary(NSObjectII, Summ, "performSelector", "onThread",
+                    "withObject", "waitUntilDone", "modes", NULL);
+  addClsMethSummary(NSObjectII, Summ, "performSelectorInBackground",
+                    "withObject", NULL);
+}
+
+void RetainSummaryManager::InitializeMethodSummaries() {
+
+  assert (ScratchArgs.isEmpty());
+
+  // Create the "init" selector.  It just acts as a pass-through for the
+  // receiver.
+  const RetainSummary *InitSumm = getPersistentSummary(ObjCInitRetE, DecRefMsg);
+  addNSObjectMethSummary(GetNullarySelector("init", Ctx), InitSumm);
+
+  // awakeAfterUsingCoder: behaves basically like an 'init' method.  It
+  // claims the receiver and returns a retained object.
+  addNSObjectMethSummary(GetUnarySelector("awakeAfterUsingCoder", Ctx),
+                         InitSumm);
+
+  // The next methods are allocators.
+  const RetainSummary *AllocSumm = getPersistentSummary(ObjCAllocRetE);
+  const RetainSummary *CFAllocSumm =
+    getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true));
+
+  // Create the "retain" selector.
+  RetEffect NoRet = RetEffect::MakeNoRet();
+  const RetainSummary *Summ = getPersistentSummary(NoRet, IncRefMsg);
+  addNSObjectMethSummary(GetNullarySelector("retain", Ctx), Summ);
+
+  // Create the "release" selector.
+  Summ = getPersistentSummary(NoRet, DecRefMsg);
+  addNSObjectMethSummary(GetNullarySelector("release", Ctx), Summ);
+
+  // Create the "drain" selector.
+  Summ = getPersistentSummary(NoRet, isGCEnabled() ? DoNothing : DecRef);
+  addNSObjectMethSummary(GetNullarySelector("drain", Ctx), Summ);
+
+  // Create the -dealloc summary.
+  Summ = getPersistentSummary(NoRet, Dealloc);
+  addNSObjectMethSummary(GetNullarySelector("dealloc", Ctx), Summ);
+
+  // Create the "autorelease" selector.
+  Summ = getPersistentSummary(NoRet, Autorelease);
+  addNSObjectMethSummary(GetNullarySelector("autorelease", Ctx), Summ);
+
+  // Specially handle NSAutoreleasePool.
+  addInstMethSummary("NSAutoreleasePool", "init",
+                     getPersistentSummary(NoRet, NewAutoreleasePool));
+
+  // For NSWindow, allocated objects are (initially) self-owned.
+  // FIXME: For now we opt for false negatives with NSWindow, as these objects
+  //  self-own themselves.  However, they only do this once they are displayed.
+  //  Thus, we need to track an NSWindow's display status.
+  //  This is tracked in <rdar://problem/6062711>.
+  //  See also http://llvm.org/bugs/show_bug.cgi?id=3714.
+  const RetainSummary *NoTrackYet = getPersistentSummary(RetEffect::MakeNoRet(),
+                                                   StopTracking,
+                                                   StopTracking);
+
+  addClassMethSummary("NSWindow", "alloc", NoTrackYet);
+
+#if 0
+  addInstMethSummary("NSWindow", NoTrackYet, "initWithContentRect",
+                     "styleMask", "backing", "defer", NULL);
+
+  addInstMethSummary("NSWindow", NoTrackYet, "initWithContentRect",
+                     "styleMask", "backing", "defer", "screen", NULL);
+#endif
+
+  // For NSPanel (which subclasses NSWindow), allocated objects are not
+  //  self-owned.
+  // FIXME: For now we don't track NSPanels. object for the same reason
+  //   as for NSWindow objects.
+  addClassMethSummary("NSPanel", "alloc", NoTrackYet);
+
+#if 0
+  addInstMethSummary("NSPanel", NoTrackYet, "initWithContentRect",
+                     "styleMask", "backing", "defer", NULL);
+
+  addInstMethSummary("NSPanel", NoTrackYet, "initWithContentRect",
+                     "styleMask", "backing", "defer", "screen", NULL);
+#endif
+
+  // Don't track allocated autorelease pools yet, as it is okay to prematurely
+  // exit a method.
+  addClassMethSummary("NSAutoreleasePool", "alloc", NoTrackYet);
+  addClassMethSummary("NSAutoreleasePool", "allocWithZone", NoTrackYet, false);
+
+  // Create summaries QCRenderer/QCView -createSnapShotImageOfType:
+  addInstMethSummary("QCRenderer", AllocSumm,
+                     "createSnapshotImageOfType", NULL);
+  addInstMethSummary("QCView", AllocSumm,
+                     "createSnapshotImageOfType", NULL);
+
+  // Create summaries for CIContext, 'createCGImage' and
+  // 'createCGLayerWithSize'.  These objects are CF objects, and are not
+  // automatically garbage collected.
+  addInstMethSummary("CIContext", CFAllocSumm,
+                     "createCGImage", "fromRect", NULL);
+  addInstMethSummary("CIContext", CFAllocSumm,
+                     "createCGImage", "fromRect", "format", "colorSpace", NULL);
+  addInstMethSummary("CIContext", CFAllocSumm, "createCGLayerWithSize",
+           "info", NULL);
+}
+
+//===----------------------------------------------------------------------===//
+// AutoreleaseBindings - State used to track objects in autorelease pools.
+//===----------------------------------------------------------------------===//
+
+typedef llvm::ImmutableMap<SymbolRef, unsigned> ARCounts;
+typedef llvm::ImmutableMap<SymbolRef, ARCounts> ARPoolContents;
+typedef llvm::ImmutableList<SymbolRef> ARStack;
+
+static int AutoRCIndex = 0;
+static int AutoRBIndex = 0;
+
+namespace { class AutoreleasePoolContents {}; }
+namespace { class AutoreleaseStack {}; }
+
+namespace clang {
+namespace ento {
+template<> struct ProgramStateTrait<AutoreleaseStack>
+  : public ProgramStatePartialTrait<ARStack> {
+  static inline void *GDMIndex() { return &AutoRBIndex; }
+};
+
+template<> struct ProgramStateTrait<AutoreleasePoolContents>
+  : public ProgramStatePartialTrait<ARPoolContents> {
+  static inline void *GDMIndex() { return &AutoRCIndex; }
+};
+} // end GR namespace
+} // end clang namespace
+
+static SymbolRef GetCurrentAutoreleasePool(ProgramStateRef state) {
+  ARStack stack = state->get<AutoreleaseStack>();
+  return stack.isEmpty() ? SymbolRef() : stack.getHead();
+}
+
+static ProgramStateRef 
+SendAutorelease(ProgramStateRef state,
+                ARCounts::Factory &F,
+                SymbolRef sym) {
+  SymbolRef pool = GetCurrentAutoreleasePool(state);
+  const ARCounts *cnts = state->get<AutoreleasePoolContents>(pool);
+  ARCounts newCnts(0);
+
+  if (cnts) {
+    const unsigned *cnt = (*cnts).lookup(sym);
+    newCnts = F.add(*cnts, sym, cnt ? *cnt  + 1 : 1);
+  }
+  else
+    newCnts = F.add(F.getEmptyMap(), sym, 1);
+
+  return state->set<AutoreleasePoolContents>(pool, newCnts);
+}
+
+//===----------------------------------------------------------------------===//
+// Error reporting.
+//===----------------------------------------------------------------------===//
+namespace {
+  typedef llvm::DenseMap<const ExplodedNode *, const RetainSummary *>
+    SummaryLogTy;
+
+  //===-------------===//
+  // Bug Descriptions. //
+  //===-------------===//
+
+  class CFRefBug : public BugType {
+  protected:
+    CFRefBug(StringRef name)
+    : BugType(name, categories::MemoryCoreFoundationObjectiveC) {}
+  public:
+
+    // FIXME: Eventually remove.
+    virtual const char *getDescription() const = 0;
+
+    virtual bool isLeak() const { return false; }
+  };
+
+  class UseAfterRelease : public CFRefBug {
+  public:
+    UseAfterRelease() : CFRefBug("Use-after-release") {}
+
+    const char *getDescription() const {
+      return "Reference-counted object is used after it is released";
+    }
+  };
+
+  class BadRelease : public CFRefBug {
+  public:
+    BadRelease() : CFRefBug("Bad release") {}
+
+    const char *getDescription() const {
+      return "Incorrect decrement of the reference count of an object that is "
+             "not owned at this point by the caller";
+    }
+  };
+
+  class DeallocGC : public CFRefBug {
+  public:
+    DeallocGC()
+    : CFRefBug("-dealloc called while using garbage collection") {}
+
+    const char *getDescription() const {
+      return "-dealloc called while using garbage collection";
+    }
+  };
+
+  class DeallocNotOwned : public CFRefBug {
+  public:
+    DeallocNotOwned()
+    : CFRefBug("-dealloc sent to non-exclusively owned object") {}
+
+    const char *getDescription() const {
+      return "-dealloc sent to object that may be referenced elsewhere";
+    }
+  };
+
+  class OverAutorelease : public CFRefBug {
+  public:
+    OverAutorelease()
+    : CFRefBug("Object sent -autorelease too many times") {}
+
+    const char *getDescription() const {
+      return "Object sent -autorelease too many times";
+    }
+  };
+
+  class ReturnedNotOwnedForOwned : public CFRefBug {
+  public:
+    ReturnedNotOwnedForOwned()
+    : CFRefBug("Method should return an owned object") {}
+
+    const char *getDescription() const {
+      return "Object with a +0 retain count returned to caller where a +1 "
+             "(owning) retain count is expected";
+    }
+  };
+
+  class Leak : public CFRefBug {
+    const bool isReturn;
+  protected:
+    Leak(StringRef name, bool isRet)
+    : CFRefBug(name), isReturn(isRet) {
+      // Leaks should not be reported if they are post-dominated by a sink.
+      setSuppressOnSink(true);
+    }
+  public:
+
+    const char *getDescription() const { return ""; }
+
+    bool isLeak() const { return true; }
+  };
+
+  class LeakAtReturn : public Leak {
+  public:
+    LeakAtReturn(StringRef name)
+    : Leak(name, true) {}
+  };
+
+  class LeakWithinFunction : public Leak {
+  public:
+    LeakWithinFunction(StringRef name)
+    : Leak(name, false) {}
+  };
+
+  //===---------===//
+  // Bug Reports.  //
+  //===---------===//
+
+  class CFRefReportVisitor : public BugReporterVisitorImpl<CFRefReportVisitor> {
+  protected:
+    SymbolRef Sym;
+    const SummaryLogTy &SummaryLog;
+    bool GCEnabled;
+    
+  public:
+    CFRefReportVisitor(SymbolRef sym, bool gcEnabled, const SummaryLogTy &log)
+       : Sym(sym), SummaryLog(log), GCEnabled(gcEnabled) {}
+
+    virtual void Profile(llvm::FoldingSetNodeID &ID) const {
+      static int x = 0;
+      ID.AddPointer(&x);
+      ID.AddPointer(Sym);
+    }
+
+    virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+                                           const ExplodedNode *PrevN,
+                                           BugReporterContext &BRC,
+                                           BugReport &BR);
+
+    virtual PathDiagnosticPiece *getEndPath(BugReporterContext &BRC,
+                                            const ExplodedNode *N,
+                                            BugReport &BR);
+  };
+
+  class CFRefLeakReportVisitor : public CFRefReportVisitor {
+  public:
+    CFRefLeakReportVisitor(SymbolRef sym, bool GCEnabled,
+                           const SummaryLogTy &log)
+       : CFRefReportVisitor(sym, GCEnabled, log) {}
+
+    PathDiagnosticPiece *getEndPath(BugReporterContext &BRC,
+                                    const ExplodedNode *N,
+                                    BugReport &BR);
+
+    virtual BugReporterVisitor *clone() const {
+      // The curiously-recurring template pattern only works for one level of
+      // subclassing. Rather than make a new template base for
+      // CFRefReportVisitor, we simply override clone() to do the right thing.
+      // This could be trouble someday if BugReporterVisitorImpl is ever
+      // used for something else besides a convenient implementation of clone().
+      return new CFRefLeakReportVisitor(*this);
+    }
+  };
+
+  class CFRefReport : public BugReport {
+    void addGCModeDescription(const LangOptions &LOpts, bool GCEnabled);
+
+  public:
+    CFRefReport(CFRefBug &D, const LangOptions &LOpts, bool GCEnabled,
+                const SummaryLogTy &Log, ExplodedNode *n, SymbolRef sym,
+                bool registerVisitor = true)
+      : BugReport(D, D.getDescription(), n) {
+      if (registerVisitor)
+        addVisitor(new CFRefReportVisitor(sym, GCEnabled, Log));
+      addGCModeDescription(LOpts, GCEnabled);
+    }
+
+    CFRefReport(CFRefBug &D, const LangOptions &LOpts, bool GCEnabled,
+                const SummaryLogTy &Log, ExplodedNode *n, SymbolRef sym,
+                StringRef endText)
+      : BugReport(D, D.getDescription(), endText, n) {
+      addVisitor(new CFRefReportVisitor(sym, GCEnabled, Log));
+      addGCModeDescription(LOpts, GCEnabled);
+    }
+
+    virtual std::pair<ranges_iterator, ranges_iterator> getRanges() {
+      const CFRefBug& BugTy = static_cast<CFRefBug&>(getBugType());
+      if (!BugTy.isLeak())
+        return BugReport::getRanges();
+      else
+        return std::make_pair(ranges_iterator(), ranges_iterator());
+    }
+  };
+
+  class CFRefLeakReport : public CFRefReport {
+    const MemRegion* AllocBinding;
+
+  public:
+    CFRefLeakReport(CFRefBug &D, const LangOptions &LOpts, bool GCEnabled,
+                    const SummaryLogTy &Log, ExplodedNode *n, SymbolRef sym,
+                    CheckerContext &Ctx);
+
+    PathDiagnosticLocation getLocation(const SourceManager &SM) const {
+      assert(Location.isValid());
+      return Location;
+    }
+  };
+} // end anonymous namespace
+
+void CFRefReport::addGCModeDescription(const LangOptions &LOpts,
+                                       bool GCEnabled) {
+  const char *GCModeDescription = 0;
+
+  switch (LOpts.getGC()) {
+  case LangOptions::GCOnly:
+    assert(GCEnabled);
+    GCModeDescription = "Code is compiled to only use garbage collection";
+    break;
+
+  case LangOptions::NonGC:
+    assert(!GCEnabled);
+    GCModeDescription = "Code is compiled to use reference counts";
+    break;
+
+  case LangOptions::HybridGC:
+    if (GCEnabled) {
+      GCModeDescription = "Code is compiled to use either garbage collection "
+                          "(GC) or reference counts (non-GC).  The bug occurs "
+                          "with GC enabled";
+      break;
+    } else {
+      GCModeDescription = "Code is compiled to use either garbage collection "
+                          "(GC) or reference counts (non-GC).  The bug occurs "
+                          "in non-GC mode";
+      break;
+    }
+  }
+
+  assert(GCModeDescription && "invalid/unknown GC mode");
+  addExtraText(GCModeDescription);
+}
+
+// FIXME: This should be a method on SmallVector.
+static inline bool contains(const SmallVectorImpl<ArgEffect>& V,
+                            ArgEffect X) {
+  for (SmallVectorImpl<ArgEffect>::const_iterator I=V.begin(), E=V.end();
+       I!=E; ++I)
+    if (*I == X) return true;
+
+  return false;
+}
+
+static bool isPropertyAccess(const Stmt *S, ParentMap &PM) {
+  unsigned maxDepth = 4;
+  while (S && maxDepth) {
+    if (const PseudoObjectExpr *PO = dyn_cast<PseudoObjectExpr>(S)) {
+      if (!isa<ObjCMessageExpr>(PO->getSyntacticForm()))
+        return true;
+      return false;
+    }
+    S = PM.getParent(S);
+    --maxDepth;
+  }
+  return false;
+}
+
+PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N,
+                                                   const ExplodedNode *PrevN,
+                                                   BugReporterContext &BRC,
+                                                   BugReport &BR) {
+
+  if (!isa<StmtPoint>(N->getLocation()))
+    return NULL;
+
+  // Check if the type state has changed.
+  ProgramStateRef PrevSt = PrevN->getState();
+  ProgramStateRef CurrSt = N->getState();
+  const LocationContext *LCtx = N->getLocationContext();
+
+  const RefVal* CurrT = CurrSt->get<RefBindings>(Sym);
+  if (!CurrT) return NULL;
+
+  const RefVal &CurrV = *CurrT;
+  const RefVal *PrevT = PrevSt->get<RefBindings>(Sym);
+
+  // Create a string buffer to constain all the useful things we want
+  // to tell the user.
+  std::string sbuf;
+  llvm::raw_string_ostream os(sbuf);
+
+  // This is the allocation site since the previous node had no bindings
+  // for this symbol.
+  if (!PrevT) {
+    const Stmt *S = cast<StmtPoint>(N->getLocation()).getStmt();
+
+    if (isa<ObjCArrayLiteral>(S)) {
+      os << "NSArray literal is an object with a +0 retain count";
+    }
+    else if (isa<ObjCDictionaryLiteral>(S)) {
+      os << "NSDictionary literal is an object with a +0 retain count";
+    }
+    else {      
+      if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
+        // Get the name of the callee (if it is available).
+        SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee(), LCtx);
+        if (const FunctionDecl *FD = X.getAsFunctionDecl())
+          os << "Call to function '" << *FD << '\'';
+        else
+          os << "function call";
+      }
+      else {
+        assert(isa<ObjCMessageExpr>(S));      
+        // The message expression may have between written directly or as
+        // a property access.  Lazily determine which case we are looking at.
+        os << (isPropertyAccess(S, N->getParentMap()) ? "Property" : "Method");
+      }
+
+      if (CurrV.getObjKind() == RetEffect::CF) {
+        os << " returns a Core Foundation object with a ";
+      }
+      else {
+        assert (CurrV.getObjKind() == RetEffect::ObjC);
+        os << " returns an Objective-C object with a ";
+      }
+
+      if (CurrV.isOwned()) {
+        os << "+1 retain count";
+
+        if (GCEnabled) {
+          assert(CurrV.getObjKind() == RetEffect::CF);
+          os << ".  "
+          "Core Foundation objects are not automatically garbage collected.";
+        }
+      }
+      else {
+        assert (CurrV.isNotOwned());
+        os << "+0 retain count";
+      }
+    }
+
+    PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
+                                  N->getLocationContext());
+    return new PathDiagnosticEventPiece(Pos, os.str());
+  }
+
+  // Gather up the effects that were performed on the object at this
+  // program point
+  SmallVector<ArgEffect, 2> AEffects;
+
+  const ExplodedNode *OrigNode = BRC.getNodeResolver().getOriginalNode(N);
+  if (const RetainSummary *Summ = SummaryLog.lookup(OrigNode)) {
+    // We only have summaries attached to nodes after evaluating CallExpr and
+    // ObjCMessageExprs.
+    const Stmt *S = cast<StmtPoint>(N->getLocation()).getStmt();
+
+    if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
+      // Iterate through the parameter expressions and see if the symbol
+      // was ever passed as an argument.
+      unsigned i = 0;
+
+      for (CallExpr::const_arg_iterator AI=CE->arg_begin(), AE=CE->arg_end();
+           AI!=AE; ++AI, ++i) {
+
+        // Retrieve the value of the argument.  Is it the symbol
+        // we are interested in?
+        if (CurrSt->getSValAsScalarOrLoc(*AI, LCtx).getAsLocSymbol() != Sym)
+          continue;
+
+        // We have an argument.  Get the effect!
+        AEffects.push_back(Summ->getArg(i));
+      }
+    }
+    else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
+      if (const Expr *receiver = ME->getInstanceReceiver())
+        if (CurrSt->getSValAsScalarOrLoc(receiver, LCtx)
+              .getAsLocSymbol() == Sym) {
+          // The symbol we are tracking is the receiver.
+          AEffects.push_back(Summ->getReceiverEffect());
+        }
+    }
+  }
+
+  do {
+    // Get the previous type state.
+    RefVal PrevV = *PrevT;
+
+    // Specially handle -dealloc.
+    if (!GCEnabled && contains(AEffects, Dealloc)) {
+      // Determine if the object's reference count was pushed to zero.
+      assert(!(PrevV == CurrV) && "The typestate *must* have changed.");
+      // We may not have transitioned to 'release' if we hit an error.
+      // This case is handled elsewhere.
+      if (CurrV.getKind() == RefVal::Released) {
+        assert(CurrV.getCombinedCounts() == 0);
+        os << "Object released by directly sending the '-dealloc' message";
+        break;
+      }
+    }
+
+    // Specially handle CFMakeCollectable and friends.
+    if (contains(AEffects, MakeCollectable)) {
+      // Get the name of the function.
+      const Stmt *S = cast<StmtPoint>(N->getLocation()).getStmt();
+      SVal X =
+        CurrSt->getSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee(), LCtx);
+      const FunctionDecl *FD = X.getAsFunctionDecl();
+
+      if (GCEnabled) {
+        // Determine if the object's reference count was pushed to zero.
+        assert(!(PrevV == CurrV) && "The typestate *must* have changed.");
+
+        os << "In GC mode a call to '" << *FD
+        <<  "' decrements an object's retain count and registers the "
+        "object with the garbage collector. ";
+
+        if (CurrV.getKind() == RefVal::Released) {
+          assert(CurrV.getCount() == 0);
+          os << "Since it now has a 0 retain count the object can be "
+          "automatically collected by the garbage collector.";
+        }
+        else
+          os << "An object must have a 0 retain count to be garbage collected. "
+          "After this call its retain count is +" << CurrV.getCount()
+          << '.';
+      }
+      else
+        os << "When GC is not enabled a call to '" << *FD
+        << "' has no effect on its argument.";
+
+      // Nothing more to say.
+      break;
+    }
+
+    // Determine if the typestate has changed.
+    if (!(PrevV == CurrV))
+      switch (CurrV.getKind()) {
+        case RefVal::Owned:
+        case RefVal::NotOwned:
+
+          if (PrevV.getCount() == CurrV.getCount()) {
+            // Did an autorelease message get sent?
+            if (PrevV.getAutoreleaseCount() == CurrV.getAutoreleaseCount())
+              return 0;
+
+            assert(PrevV.getAutoreleaseCount() < CurrV.getAutoreleaseCount());
+            os << "Object sent -autorelease message";
+            break;
+          }
+
+          if (PrevV.getCount() > CurrV.getCount())
+            os << "Reference count decremented.";
+          else
+            os << "Reference count incremented.";
+
+          if (unsigned Count = CurrV.getCount())
+            os << " The object now has a +" << Count << " retain count.";
+
+          if (PrevV.getKind() == RefVal::Released) {
+            assert(GCEnabled && CurrV.getCount() > 0);
+            os << " The object is not eligible for garbage collection until "
+                  "the retain count reaches 0 again.";
+          }
+
+          break;
+
+        case RefVal::Released:
+          os << "Object released.";
+          break;
+
+        case RefVal::ReturnedOwned:
+          // Autoreleases can be applied after marking a node ReturnedOwned.
+          if (CurrV.getAutoreleaseCount())
+            return NULL;
+
+          os << "Object returned to caller as an owning reference (single "
+                "retain count transferred to caller)";
+          break;
+
+        case RefVal::ReturnedNotOwned:
+          os << "Object returned to caller with a +0 retain count";
+          break;
+
+        default:
+          return NULL;
+      }
+
+    // Emit any remaining diagnostics for the argument effects (if any).
+    for (SmallVectorImpl<ArgEffect>::iterator I=AEffects.begin(),
+         E=AEffects.end(); I != E; ++I) {
+
+      // A bunch of things have alternate behavior under GC.
+      if (GCEnabled)
+        switch (*I) {
+          default: break;
+          case Autorelease:
+            os << "In GC mode an 'autorelease' has no effect.";
+            continue;
+          case IncRefMsg:
+            os << "In GC mode the 'retain' message has no effect.";
+            continue;
+          case DecRefMsg:
+            os << "In GC mode the 'release' message has no effect.";
+            continue;
+        }
+    }
+  } while (0);
+
+  if (os.str().empty())
+    return 0; // We have nothing to say!
+
+  const Stmt *S = cast<StmtPoint>(N->getLocation()).getStmt();
+  PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
+                                N->getLocationContext());
+  PathDiagnosticPiece *P = new PathDiagnosticEventPiece(Pos, os.str());
+
+  // Add the range by scanning the children of the statement for any bindings
+  // to Sym.
+  for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
+       I!=E; ++I)
+    if (const Expr *Exp = dyn_cast_or_null<Expr>(*I))
+      if (CurrSt->getSValAsScalarOrLoc(Exp, LCtx).getAsLocSymbol() == Sym) {
+        P->addRange(Exp->getSourceRange());
+        break;
+      }
+
+  return P;
+}
+
+// Find the first node in the current function context that referred to the
+// tracked symbol and the memory location that value was stored to. Note, the
+// value is only reported if the allocation occurred in the same function as
+// the leak.
+static std::pair<const ExplodedNode*,const MemRegion*>
+GetAllocationSite(ProgramStateManager& StateMgr, const ExplodedNode *N,
+                  SymbolRef Sym) {
+  const ExplodedNode *Last = N;
+  const MemRegion* FirstBinding = 0;
+  const LocationContext *LeakContext = N->getLocationContext();
+
+  while (N) {
+    ProgramStateRef St = N->getState();
+    RefBindings B = St->get<RefBindings>();
+
+    if (!B.lookup(Sym))
+      break;
+
+    StoreManager::FindUniqueBinding FB(Sym);
+    StateMgr.iterBindings(St, FB);
+    if (FB) FirstBinding = FB.getRegion();
+
+    // Allocation node, is the last node in the current context in which the
+    // symbol was tracked.
+    if (N->getLocationContext() == LeakContext)
+      Last = N;
+
+    N = N->pred_empty() ? NULL : *(N->pred_begin());
+  }
+
+  // If allocation happened in a function different from the leak node context,
+  // do not report the binding.
+  if (N->getLocationContext() != LeakContext) {
+    FirstBinding = 0;
+  }
+
+  return std::make_pair(Last, FirstBinding);
+}
+
+PathDiagnosticPiece*
+CFRefReportVisitor::getEndPath(BugReporterContext &BRC,
+                               const ExplodedNode *EndN,
+                               BugReport &BR) {
+  BR.markInteresting(Sym);
+  return BugReporterVisitor::getDefaultEndPath(BRC, EndN, BR);
+}
+
+PathDiagnosticPiece*
+CFRefLeakReportVisitor::getEndPath(BugReporterContext &BRC,
+                                   const ExplodedNode *EndN,
+                                   BugReport &BR) {
+
+  // Tell the BugReporterContext to report cases when the tracked symbol is
+  // assigned to different variables, etc.
+  BR.markInteresting(Sym);
+
+  // We are reporting a leak.  Walk up the graph to get to the first node where
+  // the symbol appeared, and also get the first VarDecl that tracked object
+  // is stored to.
+  const ExplodedNode *AllocNode = 0;
+  const MemRegion* FirstBinding = 0;
+
+  llvm::tie(AllocNode, FirstBinding) =
+    GetAllocationSite(BRC.getStateManager(), EndN, Sym);
+
+  SourceManager& SM = BRC.getSourceManager();
+
+  // Compute an actual location for the leak.  Sometimes a leak doesn't
+  // occur at an actual statement (e.g., transition between blocks; end
+  // of function) so we need to walk the graph and compute a real location.
+  const ExplodedNode *LeakN = EndN;
+  PathDiagnosticLocation L = PathDiagnosticLocation::createEndOfPath(LeakN, SM);
+
+  std::string sbuf;
+  llvm::raw_string_ostream os(sbuf);
+
+  os << "Object leaked: ";
+
+  if (FirstBinding) {
+    os << "object allocated and stored into '"
+       << FirstBinding->getString() << '\'';
+  }
+  else
+    os << "allocated object";
+
+  // Get the retain count.
+  const RefVal* RV = EndN->getState()->get<RefBindings>(Sym);
+
+  if (RV->getKind() == RefVal::ErrorLeakReturned) {
+    // FIXME: Per comments in rdar://6320065, "create" only applies to CF
+    // objects.  Only "copy", "alloc", "retain" and "new" transfer ownership
+    // to the caller for NS objects.
+    const Decl *D = &EndN->getCodeDecl();
+    if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+      os << " is returned from a method whose name ('"
+         << MD->getSelector().getAsString()
+         << "') does not start with 'copy', 'mutableCopy', 'alloc' or 'new'."
+            "  This violates the naming convention rules"
+            " given in the Memory Management Guide for Cocoa";
+    }
+    else {
+      const FunctionDecl *FD = cast<FunctionDecl>(D);
+      os << " is returned from a function whose name ('"
+         << *FD
+         << "') does not contain 'Copy' or 'Create'.  This violates the naming"
+            " convention rules given in the Memory Management Guide for Core"
+            " Foundation";
+    }    
+  }
+  else if (RV->getKind() == RefVal::ErrorGCLeakReturned) {
+    ObjCMethodDecl &MD = cast<ObjCMethodDecl>(EndN->getCodeDecl());
+    os << " and returned from method '" << MD.getSelector().getAsString()
+       << "' is potentially leaked when using garbage collection.  Callers "
+          "of this method do not expect a returned object with a +1 retain "
+          "count since they expect the object to be managed by the garbage "
+          "collector";
+  }
+  else
+    os << " is not referenced later in this execution path and has a retain "
+          "count of +" << RV->getCount();
+
+  return new PathDiagnosticEventPiece(L, os.str());
+}
+
+CFRefLeakReport::CFRefLeakReport(CFRefBug &D, const LangOptions &LOpts,
+                                 bool GCEnabled, const SummaryLogTy &Log, 
+                                 ExplodedNode *n, SymbolRef sym,
+                                 CheckerContext &Ctx)
+: CFRefReport(D, LOpts, GCEnabled, Log, n, sym, false) {
+
+  // Most bug reports are cached at the location where they occurred.
+  // With leaks, we want to unique them by the location where they were
+  // allocated, and only report a single path.  To do this, we need to find
+  // the allocation site of a piece of tracked memory, which we do via a
+  // call to GetAllocationSite.  This will walk the ExplodedGraph backwards.
+  // Note that this is *not* the trimmed graph; we are guaranteed, however,
+  // that all ancestor nodes that represent the allocation site have the
+  // same SourceLocation.
+  const ExplodedNode *AllocNode = 0;
+
+  const SourceManager& SMgr = Ctx.getSourceManager();
+
+  llvm::tie(AllocNode, AllocBinding) =  // Set AllocBinding.
+    GetAllocationSite(Ctx.getStateManager(), getErrorNode(), sym);
+
+  // Get the SourceLocation for the allocation site.
+  ProgramPoint P = AllocNode->getLocation();
+  const Stmt *AllocStmt = cast<PostStmt>(P).getStmt();
+  Location = PathDiagnosticLocation::createBegin(AllocStmt, SMgr,
+                                                  n->getLocationContext());
+  // Fill in the description of the bug.
+  Description.clear();
+  llvm::raw_string_ostream os(Description);
+  os << "Potential leak ";
+  if (GCEnabled)
+    os << "(when using garbage collection) ";
+  os << "of an object";
+
+  // FIXME: AllocBinding doesn't get populated for RegionStore yet.
+  if (AllocBinding)
+    os << " stored into '" << AllocBinding->getString() << '\'';
+
+  addVisitor(new CFRefLeakReportVisitor(sym, GCEnabled, Log));
+}
+
+//===----------------------------------------------------------------------===//
+// Main checker logic.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class RetainCountChecker
+  : public Checker< check::Bind,
+                    check::DeadSymbols,
+                    check::EndAnalysis,
+                    check::EndPath,
+                    check::PostStmt<BlockExpr>,
+                    check::PostStmt<CastExpr>,
+                    check::PostStmt<CallExpr>,
+                    check::PostStmt<CXXConstructExpr>,
+                    check::PostStmt<ObjCArrayLiteral>,
+                    check::PostStmt<ObjCDictionaryLiteral>,
+                    check::PostObjCMessage,
+                    check::PreStmt<ReturnStmt>,
+                    check::RegionChanges,
+                    eval::Assume,
+                    eval::Call > {
+  mutable OwningPtr<CFRefBug> useAfterRelease, releaseNotOwned;
+  mutable OwningPtr<CFRefBug> deallocGC, deallocNotOwned;
+  mutable OwningPtr<CFRefBug> overAutorelease, returnNotOwnedForOwned;
+  mutable OwningPtr<CFRefBug> leakWithinFunction, leakAtReturn;
+  mutable OwningPtr<CFRefBug> leakWithinFunctionGC, leakAtReturnGC;
+
+  typedef llvm::DenseMap<SymbolRef, const SimpleProgramPointTag *> SymbolTagMap;
+
+  // This map is only used to ensure proper deletion of any allocated tags.
+  mutable SymbolTagMap DeadSymbolTags;
+
+  mutable OwningPtr<RetainSummaryManager> Summaries;
+  mutable OwningPtr<RetainSummaryManager> SummariesGC;
+
+  mutable ARCounts::Factory ARCountFactory;
+
+  mutable SummaryLogTy SummaryLog;
+  mutable bool ShouldResetSummaryLog;
+
+public:  
+  RetainCountChecker() : ShouldResetSummaryLog(false) {}
+
+  virtual ~RetainCountChecker() {
+    DeleteContainerSeconds(DeadSymbolTags);
+  }
+
+  void checkEndAnalysis(ExplodedGraph &G, BugReporter &BR,
+                        ExprEngine &Eng) const {
+    // FIXME: This is a hack to make sure the summary log gets cleared between
+    // analyses of different code bodies.
+    //
+    // Why is this necessary? Because a checker's lifetime is tied to a
+    // translation unit, but an ExplodedGraph's lifetime is just a code body.
+    // Once in a blue moon, a new ExplodedNode will have the same address as an
+    // old one with an associated summary, and the bug report visitor gets very
+    // confused. (To make things worse, the summary lifetime is currently also
+    // tied to a code body, so we get a crash instead of incorrect results.)
+    //
+    // Why is this a bad solution? Because if the lifetime of the ExplodedGraph
+    // changes, things will start going wrong again. Really the lifetime of this
+    // log needs to be tied to either the specific nodes in it or the entire
+    // ExplodedGraph, not to a specific part of the code being analyzed.
+    //
+    // (Also, having stateful local data means that the same checker can't be
+    // used from multiple threads, but a lot of checkers have incorrect
+    // assumptions about that anyway. So that wasn't a priority at the time of
+    // this fix.)
+    //
+    // This happens at the end of analysis, but bug reports are emitted /after/
+    // this point. So we can't just clear the summary log now. Instead, we mark
+    // that the next time we access the summary log, it should be cleared.
+
+    // If we never reset the summary log during /this/ code body analysis,
+    // there were no new summaries. There might still have been summaries from
+    // the /last/ analysis, so clear them out to make sure the bug report
+    // visitors don't get confused.
+    if (ShouldResetSummaryLog)
+      SummaryLog.clear();
+
+    ShouldResetSummaryLog = !SummaryLog.empty();
+  }
+
+  CFRefBug *getLeakWithinFunctionBug(const LangOptions &LOpts,
+                                     bool GCEnabled) const {
+    if (GCEnabled) {
+      if (!leakWithinFunctionGC)
+        leakWithinFunctionGC.reset(new LeakWithinFunction("Leak of object when "
+                                                          "using garbage "
+                                                          "collection"));
+      return leakWithinFunctionGC.get();
+    } else {
+      if (!leakWithinFunction) {
+        if (LOpts.getGC() == LangOptions::HybridGC) {
+          leakWithinFunction.reset(new LeakWithinFunction("Leak of object when "
+                                                          "not using garbage "
+                                                          "collection (GC) in "
+                                                          "dual GC/non-GC "
+                                                          "code"));
+        } else {
+          leakWithinFunction.reset(new LeakWithinFunction("Leak"));
+        }
+      }
+      return leakWithinFunction.get();
+    }
+  }
+
+  CFRefBug *getLeakAtReturnBug(const LangOptions &LOpts, bool GCEnabled) const {
+    if (GCEnabled) {
+      if (!leakAtReturnGC)
+        leakAtReturnGC.reset(new LeakAtReturn("Leak of returned object when "
+                                              "using garbage collection"));
+      return leakAtReturnGC.get();
+    } else {
+      if (!leakAtReturn) {
+        if (LOpts.getGC() == LangOptions::HybridGC) {
+          leakAtReturn.reset(new LeakAtReturn("Leak of returned object when "
+                                              "not using garbage collection "
+                                              "(GC) in dual GC/non-GC code"));
+        } else {
+          leakAtReturn.reset(new LeakAtReturn("Leak of returned object"));
+        }
+      }
+      return leakAtReturn.get();
+    }
+  }
+
+  RetainSummaryManager &getSummaryManager(ASTContext &Ctx,
+                                          bool GCEnabled) const {
+    // FIXME: We don't support ARC being turned on and off during one analysis.
+    // (nor, for that matter, do we support changing ASTContexts)
+    bool ARCEnabled = (bool)Ctx.getLangOpts().ObjCAutoRefCount;
+    if (GCEnabled) {
+      if (!SummariesGC)
+        SummariesGC.reset(new RetainSummaryManager(Ctx, true, ARCEnabled));
+      else
+        assert(SummariesGC->isARCEnabled() == ARCEnabled);
+      return *SummariesGC;
+    } else {
+      if (!Summaries)
+        Summaries.reset(new RetainSummaryManager(Ctx, false, ARCEnabled));
+      else
+        assert(Summaries->isARCEnabled() == ARCEnabled);
+      return *Summaries;
+    }
+  }
+
+  RetainSummaryManager &getSummaryManager(CheckerContext &C) const {
+    return getSummaryManager(C.getASTContext(), C.isObjCGCEnabled());
+  }
+
+  void printState(raw_ostream &Out, ProgramStateRef State,
+                  const char *NL, const char *Sep) const;
+
+  void checkBind(SVal loc, SVal val, const Stmt *S, CheckerContext &C) const;
+  void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
+  void checkPostStmt(const CastExpr *CE, CheckerContext &C) const;
+
+  void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
+  void checkPostStmt(const CXXConstructExpr *CE, CheckerContext &C) const;
+  void checkPostStmt(const ObjCArrayLiteral *AL, CheckerContext &C) const;
+  void checkPostStmt(const ObjCDictionaryLiteral *DL, CheckerContext &C) const;
+  void checkPostObjCMessage(const ObjCMessage &Msg, CheckerContext &C) const;
+                      
+  void checkSummary(const RetainSummary &Summ, const CallOrObjCMessage &Call,
+                    CheckerContext &C) const;
+
+  bool evalCall(const CallExpr *CE, CheckerContext &C) const;
+
+  ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond,
+                                 bool Assumption) const;
+
+  ProgramStateRef 
+  checkRegionChanges(ProgramStateRef state,
+                     const StoreManager::InvalidatedSymbols *invalidated,
+                     ArrayRef<const MemRegion *> ExplicitRegions,
+                     ArrayRef<const MemRegion *> Regions,
+                     const CallOrObjCMessage *Call) const;
+                                        
+  bool wantsRegionChangeUpdate(ProgramStateRef state) const {
+    return true;
+  }
+
+  void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
+  void checkReturnWithRetEffect(const ReturnStmt *S, CheckerContext &C,
+                                ExplodedNode *Pred, RetEffect RE, RefVal X,
+                                SymbolRef Sym, ProgramStateRef state) const;
+                                              
+  void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
+  void checkEndPath(CheckerContext &C) const;
+
+  ProgramStateRef updateSymbol(ProgramStateRef state, SymbolRef sym,
+                                   RefVal V, ArgEffect E, RefVal::Kind &hasErr,
+                                   CheckerContext &C) const;
+
+  void processNonLeakError(ProgramStateRef St, SourceRange ErrorRange,
+                           RefVal::Kind ErrorKind, SymbolRef Sym,
+                           CheckerContext &C) const;
+                      
+  void processObjCLiterals(CheckerContext &C, const Expr *Ex) const;
+
+  const ProgramPointTag *getDeadSymbolTag(SymbolRef sym) const;
+
+  ProgramStateRef handleSymbolDeath(ProgramStateRef state,
+                                        SymbolRef sid, RefVal V,
+                                      SmallVectorImpl<SymbolRef> &Leaked) const;
+
+  std::pair<ExplodedNode *, ProgramStateRef >
+  handleAutoreleaseCounts(ProgramStateRef state, 
+                          GenericNodeBuilderRefCount Bd, ExplodedNode *Pred,
+                          CheckerContext &Ctx, SymbolRef Sym, RefVal V) const;
+
+  ExplodedNode *processLeaks(ProgramStateRef state,
+                             SmallVectorImpl<SymbolRef> &Leaked,
+                             GenericNodeBuilderRefCount &Builder,
+                             CheckerContext &Ctx,
+                             ExplodedNode *Pred = 0) const;
+};
+} // end anonymous namespace
+
+namespace {
+class StopTrackingCallback : public SymbolVisitor {
+  ProgramStateRef state;
+public:
+  StopTrackingCallback(ProgramStateRef st) : state(st) {}
+  ProgramStateRef getState() const { return state; }
+
+  bool VisitSymbol(SymbolRef sym) {
+    state = state->remove<RefBindings>(sym);
+    return true;
+  }
+};
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Handle statements that may have an effect on refcounts.
+//===----------------------------------------------------------------------===//
+
+void RetainCountChecker::checkPostStmt(const BlockExpr *BE,
+                                       CheckerContext &C) const {
+
+  // Scan the BlockDecRefExprs for any object the retain count checker
+  // may be tracking.
+  if (!BE->getBlockDecl()->hasCaptures())
+    return;
+
+  ProgramStateRef state = C.getState();
+  const BlockDataRegion *R =
+    cast<BlockDataRegion>(state->getSVal(BE,
+                                         C.getLocationContext()).getAsRegion());
+
+  BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
+                                            E = R->referenced_vars_end();
+
+  if (I == E)
+    return;
+
+  // FIXME: For now we invalidate the tracking of all symbols passed to blocks
+  // via captured variables, even though captured variables result in a copy
+  // and in implicit increment/decrement of a retain count.
+  SmallVector<const MemRegion*, 10> Regions;
+  const LocationContext *LC = C.getLocationContext();
+  MemRegionManager &MemMgr = C.getSValBuilder().getRegionManager();
+
+  for ( ; I != E; ++I) {
+    const VarRegion *VR = *I;
+    if (VR->getSuperRegion() == R) {
+      VR = MemMgr.getVarRegion(VR->getDecl(), LC);
+    }
+    Regions.push_back(VR);
+  }
+
+  state =
+    state->scanReachableSymbols<StopTrackingCallback>(Regions.data(),
+                                    Regions.data() + Regions.size()).getState();
+  C.addTransition(state);
+}
+
+void RetainCountChecker::checkPostStmt(const CastExpr *CE,
+                                       CheckerContext &C) const {
+  const ObjCBridgedCastExpr *BE = dyn_cast<ObjCBridgedCastExpr>(CE);
+  if (!BE)
+    return;
+  
+  ArgEffect AE = IncRef;
+  
+  switch (BE->getBridgeKind()) {
+    case clang::OBC_Bridge:
+      // Do nothing.
+      return;
+    case clang::OBC_BridgeRetained:
+      AE = IncRef;
+      break;      
+    case clang::OBC_BridgeTransfer:
+      AE = DecRefBridgedTransfered;
+      break;
+  }
+  
+  ProgramStateRef state = C.getState();
+  SymbolRef Sym = state->getSVal(CE, C.getLocationContext()).getAsLocSymbol();
+  if (!Sym)
+    return;
+  const RefVal* T = state->get<RefBindings>(Sym);
+  if (!T)
+    return;
+
+  RefVal::Kind hasErr = (RefVal::Kind) 0;
+  state = updateSymbol(state, Sym, *T, AE, hasErr, C);
+  
+  if (hasErr) {
+    // FIXME: If we get an error during a bridge cast, should we report it?
+    // Should we assert that there is no error?
+    return;
+  }
+
+  C.addTransition(state);
+}
+
+void RetainCountChecker::checkPostStmt(const CallExpr *CE,
+                                       CheckerContext &C) const {
+  if (C.wasInlined)
+    return;
+  
+  // Get the callee.
+  ProgramStateRef state = C.getState();
+  const Expr *Callee = CE->getCallee();
+  SVal L = state->getSVal(Callee, C.getLocationContext());
+
+  RetainSummaryManager &Summaries = getSummaryManager(C);
+  const RetainSummary *Summ = 0;
+
+  // FIXME: Better support for blocks.  For now we stop tracking anything
+  // that is passed to blocks.
+  // FIXME: Need to handle variables that are "captured" by the block.
+  if (dyn_cast_or_null<BlockDataRegion>(L.getAsRegion())) {
+    Summ = Summaries.getPersistentStopSummary();
+  } else if (const FunctionDecl *FD = L.getAsFunctionDecl()) {
+    Summ = Summaries.getSummary(FD);
+  } else if (const CXXMemberCallExpr *me = dyn_cast<CXXMemberCallExpr>(CE)) {
+    if (const CXXMethodDecl *MD = me->getMethodDecl())
+      Summ = Summaries.getSummary(MD);
+  }
+
+  if (!Summ)
+    Summ = Summaries.getDefaultSummary();
+
+  checkSummary(*Summ, CallOrObjCMessage(CE, state, C.getLocationContext()), C);
+}
+
+void RetainCountChecker::checkPostStmt(const CXXConstructExpr *CE,
+                                       CheckerContext &C) const {
+  const CXXConstructorDecl *Ctor = CE->getConstructor();
+  if (!Ctor)
+    return;
+
+  RetainSummaryManager &Summaries = getSummaryManager(C);
+  const RetainSummary *Summ = Summaries.getSummary(Ctor);
+
+  // If we didn't get a summary, this constructor doesn't affect retain counts.
+  if (!Summ)
+    return;
+
+  ProgramStateRef state = C.getState();
+  checkSummary(*Summ, CallOrObjCMessage(CE, state, C.getLocationContext()), C);
+}
+
+void RetainCountChecker::processObjCLiterals(CheckerContext &C,
+                                             const Expr *Ex) const {
+  ProgramStateRef state = C.getState();
+  const ExplodedNode *pred = C.getPredecessor();  
+  for (Stmt::const_child_iterator it = Ex->child_begin(), et = Ex->child_end() ;
+       it != et ; ++it) {
+    const Stmt *child = *it;
+    SVal V = state->getSVal(child, pred->getLocationContext());
+    if (SymbolRef sym = V.getAsSymbol())
+      if (const RefVal* T = state->get<RefBindings>(sym)) {
+        RefVal::Kind hasErr = (RefVal::Kind) 0;
+        state = updateSymbol(state, sym, *T, MayEscape, hasErr, C);
+        if (hasErr) {
+          processNonLeakError(state, child->getSourceRange(), hasErr, sym, C);
+          return;
+        }
+      }
+  }
+  
+  // Return the object as autoreleased.
+  //  RetEffect RE = RetEffect::MakeNotOwned(RetEffect::ObjC);
+  if (SymbolRef sym = 
+        state->getSVal(Ex, pred->getLocationContext()).getAsSymbol()) {
+    QualType ResultTy = Ex->getType();
+    state = state->set<RefBindings>(sym, RefVal::makeNotOwned(RetEffect::ObjC,
+                                                              ResultTy));
+  }
+  
+  C.addTransition(state);  
+}
+
+void RetainCountChecker::checkPostStmt(const ObjCArrayLiteral *AL,
+                                       CheckerContext &C) const {
+  // Apply the 'MayEscape' to all values.
+  processObjCLiterals(C, AL);
+}
+
+void RetainCountChecker::checkPostStmt(const ObjCDictionaryLiteral *DL,
+                                       CheckerContext &C) const {
+  // Apply the 'MayEscape' to all keys and values.
+  processObjCLiterals(C, DL);
+}
+
+void RetainCountChecker::checkPostObjCMessage(const ObjCMessage &Msg, 
+                                              CheckerContext &C) const {
+  ProgramStateRef state = C.getState();
+
+  RetainSummaryManager &Summaries = getSummaryManager(C);
+
+  const RetainSummary *Summ;
+  if (Msg.isInstanceMessage()) {
+    const LocationContext *LC = C.getLocationContext();
+    Summ = Summaries.getInstanceMethodSummary(Msg, state, LC);
+  } else {
+    Summ = Summaries.getClassMethodSummary(Msg);    
+  }
+
+  // If we didn't get a summary, this message doesn't affect retain counts.
+  if (!Summ)
+    return;
+
+  checkSummary(*Summ, CallOrObjCMessage(Msg, state, C.getLocationContext()), C);
+}
+
+/// GetReturnType - Used to get the return type of a message expression or
+///  function call with the intention of affixing that type to a tracked symbol.
+///  While the the return type can be queried directly from RetEx, when
+///  invoking class methods we augment to the return type to be that of
+///  a pointer to the class (as opposed it just being id).
+// FIXME: We may be able to do this with related result types instead.
+// This function is probably overestimating.
+static QualType GetReturnType(const Expr *RetE, ASTContext &Ctx) {
+  QualType RetTy = RetE->getType();
+  // If RetE is not a message expression just return its type.
+  // If RetE is a message expression, return its types if it is something
+  /// more specific than id.
+  if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(RetE))
+    if (const ObjCObjectPointerType *PT = RetTy->getAs<ObjCObjectPointerType>())
+      if (PT->isObjCQualifiedIdType() || PT->isObjCIdType() ||
+          PT->isObjCClassType()) {
+        // At this point we know the return type of the message expression is
+        // id, id<...>, or Class. If we have an ObjCInterfaceDecl, we know this
+        // is a call to a class method whose type we can resolve.  In such
+        // cases, promote the return type to XXX* (where XXX is the class).
+        const ObjCInterfaceDecl *D = ME->getReceiverInterface();
+        return !D ? RetTy :
+                    Ctx.getObjCObjectPointerType(Ctx.getObjCInterfaceType(D));
+      }
+
+  return RetTy;
+}
+
+void RetainCountChecker::checkSummary(const RetainSummary &Summ,
+                                      const CallOrObjCMessage &CallOrMsg,
+                                      CheckerContext &C) const {
+  ProgramStateRef state = C.getState();
+
+  // Evaluate the effect of the arguments.
+  RefVal::Kind hasErr = (RefVal::Kind) 0;
+  SourceRange ErrorRange;
+  SymbolRef ErrorSym = 0;
+
+  for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
+    SVal V = CallOrMsg.getArgSVal(idx);
+
+    if (SymbolRef Sym = V.getAsLocSymbol()) {
+      if (RefBindings::data_type *T = state->get<RefBindings>(Sym)) {
+        state = updateSymbol(state, Sym, *T, Summ.getArg(idx), hasErr, C);
+        if (hasErr) {
+          ErrorRange = CallOrMsg.getArgSourceRange(idx);
+          ErrorSym = Sym;
+          break;
+        }
+      }
+    }
+  }
+
+  // Evaluate the effect on the message receiver.
+  bool ReceiverIsTracked = false;
+  if (!hasErr && CallOrMsg.isObjCMessage()) {
+    const LocationContext *LC = C.getLocationContext();
+    SVal Receiver = CallOrMsg.getInstanceMessageReceiver(LC);
+    if (SymbolRef Sym = Receiver.getAsLocSymbol()) {
+      if (const RefVal *T = state->get<RefBindings>(Sym)) {
+        ReceiverIsTracked = true;
+        state = updateSymbol(state, Sym, *T, Summ.getReceiverEffect(),
+                             hasErr, C);
+        if (hasErr) {
+          ErrorRange = CallOrMsg.getReceiverSourceRange();
+          ErrorSym = Sym;
+        }
+      }
+    }
+  }
+
+  // Process any errors.
+  if (hasErr) {
+    processNonLeakError(state, ErrorRange, hasErr, ErrorSym, C);
+    return;
+  }
+
+  // Consult the summary for the return value.
+  RetEffect RE = Summ.getRetEffect();
+
+  if (RE.getKind() == RetEffect::OwnedWhenTrackedReceiver) {
+    if (ReceiverIsTracked)
+      RE = getSummaryManager(C).getObjAllocRetEffect();      
+    else
+      RE = RetEffect::MakeNoRet();
+  }
+
+  switch (RE.getKind()) {
+    default:
+      llvm_unreachable("Unhandled RetEffect.");
+
+    case RetEffect::NoRet:
+      // No work necessary.
+      break;
+
+    case RetEffect::OwnedAllocatedSymbol:
+    case RetEffect::OwnedSymbol: {
+      SymbolRef Sym = state->getSVal(CallOrMsg.getOriginExpr(),
+                                     C.getLocationContext()).getAsSymbol();
+      if (!Sym)
+        break;
+
+      // Use the result type from callOrMsg as it automatically adjusts
+      // for methods/functions that return references.
+      QualType ResultTy = CallOrMsg.getResultType(C.getASTContext());
+      state = state->set<RefBindings>(Sym, RefVal::makeOwned(RE.getObjKind(),
+                                                             ResultTy));
+
+      // FIXME: Add a flag to the checker where allocations are assumed to
+      // *not* fail. (The code below is out-of-date, though.)
+#if 0
+      if (RE.getKind() == RetEffect::OwnedAllocatedSymbol) {
+        bool isFeasible;
+        state = state.assume(loc::SymbolVal(Sym), true, isFeasible);
+        assert(isFeasible && "Cannot assume fresh symbol is non-null.");
+      }
+#endif
+
+      break;
+    }
+
+    case RetEffect::GCNotOwnedSymbol:
+    case RetEffect::ARCNotOwnedSymbol:
+    case RetEffect::NotOwnedSymbol: {
+      const Expr *Ex = CallOrMsg.getOriginExpr();
+      SymbolRef Sym = state->getSVal(Ex, C.getLocationContext()).getAsSymbol();
+      if (!Sym)
+        break;
+
+      // Use GetReturnType in order to give [NSFoo alloc] the type NSFoo *.
+      QualType ResultTy = GetReturnType(Ex, C.getASTContext());
+      state = state->set<RefBindings>(Sym, RefVal::makeNotOwned(RE.getObjKind(),
+                                                                ResultTy));
+      break;
+    }
+  }
+
+  // This check is actually necessary; otherwise the statement builder thinks
+  // we've hit a previously-found path.
+  // Normally addTransition takes care of this, but we want the node pointer.
+  ExplodedNode *NewNode;
+  if (state == C.getState()) {
+    NewNode = C.getPredecessor();
+  } else {
+    NewNode = C.addTransition(state);
+  }
+
+  // Annotate the node with summary we used.
+  if (NewNode) {
+    // FIXME: This is ugly. See checkEndAnalysis for why it's necessary.
+    if (ShouldResetSummaryLog) {
+      SummaryLog.clear();
+      ShouldResetSummaryLog = false;
+    }
+    SummaryLog[NewNode] = &Summ;
+  }
+}
+
+
+ProgramStateRef 
+RetainCountChecker::updateSymbol(ProgramStateRef state, SymbolRef sym,
+                                 RefVal V, ArgEffect E, RefVal::Kind &hasErr,
+                                 CheckerContext &C) const {
+  // In GC mode [... release] and [... retain] do nothing.
+  // In ARC mode they shouldn't exist at all, but we just ignore them.
+  bool IgnoreRetainMsg = C.isObjCGCEnabled();
+  if (!IgnoreRetainMsg)
+    IgnoreRetainMsg = (bool)C.getASTContext().getLangOpts().ObjCAutoRefCount;
+
+  switch (E) {
+    default: break;
+    case IncRefMsg: E = IgnoreRetainMsg ? DoNothing : IncRef; break;
+    case DecRefMsg: E = IgnoreRetainMsg ? DoNothing : DecRef; break;
+    case MakeCollectable: E = C.isObjCGCEnabled() ? DecRef : DoNothing; break;
+    case NewAutoreleasePool: E = C.isObjCGCEnabled() ? DoNothing :
+                                                      NewAutoreleasePool; break;
+  }
+
+  // Handle all use-after-releases.
+  if (!C.isObjCGCEnabled() && V.getKind() == RefVal::Released) {
+    V = V ^ RefVal::ErrorUseAfterRelease;
+    hasErr = V.getKind();
+    return state->set<RefBindings>(sym, V);
+  }
+
+  switch (E) {
+    case DecRefMsg:
+    case IncRefMsg:
+    case MakeCollectable:
+      llvm_unreachable("DecRefMsg/IncRefMsg/MakeCollectable already converted");
+
+    case Dealloc:
+      // Any use of -dealloc in GC is *bad*.
+      if (C.isObjCGCEnabled()) {
+        V = V ^ RefVal::ErrorDeallocGC;
+        hasErr = V.getKind();
+        break;
+      }
+
+      switch (V.getKind()) {
+        default:
+          llvm_unreachable("Invalid RefVal state for an explicit dealloc.");
+        case RefVal::Owned:
+          // The object immediately transitions to the released state.
+          V = V ^ RefVal::Released;
+          V.clearCounts();
+          return state->set<RefBindings>(sym, V);
+        case RefVal::NotOwned:
+          V = V ^ RefVal::ErrorDeallocNotOwned;
+          hasErr = V.getKind();
+          break;
+      }
+      break;
+
+    case NewAutoreleasePool:
+      assert(!C.isObjCGCEnabled());
+      return state->add<AutoreleaseStack>(sym);
+
+    case MayEscape:
+      if (V.getKind() == RefVal::Owned) {
+        V = V ^ RefVal::NotOwned;
+        break;
+      }
+
+      // Fall-through.
+
+    case DoNothing:
+      return state;
+
+    case Autorelease:
+      if (C.isObjCGCEnabled())
+        return state;
+
+      // Update the autorelease counts.
+      state = SendAutorelease(state, ARCountFactory, sym);
+      V = V.autorelease();
+      break;
+
+    case StopTracking:
+      return state->remove<RefBindings>(sym);
+
+    case IncRef:
+      switch (V.getKind()) {
+        default:
+          llvm_unreachable("Invalid RefVal state for a retain.");
+        case RefVal::Owned:
+        case RefVal::NotOwned:
+          V = V + 1;
+          break;
+        case RefVal::Released:
+          // Non-GC cases are handled above.
+          assert(C.isObjCGCEnabled());
+          V = (V ^ RefVal::Owned) + 1;
+          break;
+      }
+      break;
+
+    case SelfOwn:
+      V = V ^ RefVal::NotOwned;
+      // Fall-through.
+    case DecRef:
+    case DecRefBridgedTransfered:
+      switch (V.getKind()) {
+        default:
+          // case 'RefVal::Released' handled above.
+          llvm_unreachable("Invalid RefVal state for a release.");
+
+        case RefVal::Owned:
+          assert(V.getCount() > 0);
+          if (V.getCount() == 1)
+            V = V ^ (E == DecRefBridgedTransfered ? 
+                      RefVal::NotOwned : RefVal::Released);
+          V = V - 1;
+          break;
+
+        case RefVal::NotOwned:
+          if (V.getCount() > 0)
+            V = V - 1;
+          else {
+            V = V ^ RefVal::ErrorReleaseNotOwned;
+            hasErr = V.getKind();
+          }
+          break;
+
+        case RefVal::Released:
+          // Non-GC cases are handled above.
+          assert(C.isObjCGCEnabled());
+          V = V ^ RefVal::ErrorUseAfterRelease;
+          hasErr = V.getKind();
+          break;
+      }
+      break;
+  }
+  return state->set<RefBindings>(sym, V);
+}
+
+void RetainCountChecker::processNonLeakError(ProgramStateRef St,
+                                             SourceRange ErrorRange,
+                                             RefVal::Kind ErrorKind,
+                                             SymbolRef Sym,
+                                             CheckerContext &C) const {
+  ExplodedNode *N = C.generateSink(St);
+  if (!N)
+    return;
+
+  CFRefBug *BT;
+  switch (ErrorKind) {
+    default:
+      llvm_unreachable("Unhandled error.");
+    case RefVal::ErrorUseAfterRelease:
+      if (!useAfterRelease)
+        useAfterRelease.reset(new UseAfterRelease());
+      BT = &*useAfterRelease;
+      break;
+    case RefVal::ErrorReleaseNotOwned:
+      if (!releaseNotOwned)
+        releaseNotOwned.reset(new BadRelease());
+      BT = &*releaseNotOwned;
+      break;
+    case RefVal::ErrorDeallocGC:
+      if (!deallocGC)
+        deallocGC.reset(new DeallocGC());
+      BT = &*deallocGC;
+      break;
+    case RefVal::ErrorDeallocNotOwned:
+      if (!deallocNotOwned)
+        deallocNotOwned.reset(new DeallocNotOwned());
+      BT = &*deallocNotOwned;
+      break;
+  }
+
+  assert(BT);
+  CFRefReport *report = new CFRefReport(*BT, C.getASTContext().getLangOpts(),
+                                        C.isObjCGCEnabled(), SummaryLog,
+                                        N, Sym);
+  report->addRange(ErrorRange);
+  C.EmitReport(report);
+}
+
+//===----------------------------------------------------------------------===//
+// Handle the return values of retain-count-related functions.
+//===----------------------------------------------------------------------===//
+
+bool RetainCountChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
+  // Get the callee. We're only interested in simple C functions.
+  ProgramStateRef state = C.getState();
+  const FunctionDecl *FD = C.getCalleeDecl(CE);
+  if (!FD)
+    return false;
+
+  IdentifierInfo *II = FD->getIdentifier();
+  if (!II)
+    return false;
+
+  // For now, we're only handling the functions that return aliases of their
+  // arguments: CFRetain and CFMakeCollectable (and their families).
+  // Eventually we should add other functions we can model entirely,
+  // such as CFRelease, which don't invalidate their arguments or globals.
+  if (CE->getNumArgs() != 1)
+    return false;
+
+  // Get the name of the function.
+  StringRef FName = II->getName();
+  FName = FName.substr(FName.find_first_not_of('_'));
+
+  // See if it's one of the specific functions we know how to eval.
+  bool canEval = false;
+
+  QualType ResultTy = CE->getCallReturnType();
+  if (ResultTy->isObjCIdType()) {
+    // Handle: id NSMakeCollectable(CFTypeRef)
+    canEval = II->isStr("NSMakeCollectable");
+  } else if (ResultTy->isPointerType()) {
+    // Handle: (CF|CG)Retain
+    //         CFMakeCollectable
+    // It's okay to be a little sloppy here (CGMakeCollectable doesn't exist).
+    if (cocoa::isRefType(ResultTy, "CF", FName) ||
+        cocoa::isRefType(ResultTy, "CG", FName)) {
+      canEval = isRetain(FD, FName) || isMakeCollectable(FD, FName);
+    }
+  }
+        
+  if (!canEval)
+    return false;
+
+  // Bind the return value.
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal RetVal = state->getSVal(CE->getArg(0), LCtx);
+  if (RetVal.isUnknown()) {
+    // If the receiver is unknown, conjure a return value.
+    SValBuilder &SVB = C.getSValBuilder();
+    unsigned Count = C.getCurrentBlockCount();
+    SVal RetVal = SVB.getConjuredSymbolVal(0, CE, LCtx, ResultTy, Count);
+  }
+  state = state->BindExpr(CE, LCtx, RetVal, false);
+
+  // FIXME: This should not be necessary, but otherwise the argument seems to be
+  // considered alive during the next statement.
+  if (const MemRegion *ArgRegion = RetVal.getAsRegion()) {
+    // Save the refcount status of the argument.
+    SymbolRef Sym = RetVal.getAsLocSymbol();
+    RefBindings::data_type *Binding = 0;
+    if (Sym)
+      Binding = state->get<RefBindings>(Sym);
+
+    // Invalidate the argument region.
+    unsigned Count = C.getCurrentBlockCount();
+    state = state->invalidateRegions(ArgRegion, CE, Count, LCtx);
+
+    // Restore the refcount status of the argument.
+    if (Binding)
+      state = state->set<RefBindings>(Sym, *Binding);
+  }
+
+  C.addTransition(state);
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// Handle return statements.
+//===----------------------------------------------------------------------===//
+
+// Return true if the current LocationContext has no caller context.
+static bool inTopFrame(CheckerContext &C) {
+  const LocationContext *LC = C.getLocationContext();
+  return LC->getParent() == 0;  
+}
+
+void RetainCountChecker::checkPreStmt(const ReturnStmt *S,
+                                      CheckerContext &C) const {
+
+  // Only adjust the reference count if this is the top-level call frame,
+  // and not the result of inlining.  In the future, we should do
+  // better checking even for inlined calls, and see if they match
+  // with their expected semantics (e.g., the method should return a retained
+  // object, etc.).
+  if (!inTopFrame(C))
+    return;
+
+  const Expr *RetE = S->getRetValue();
+  if (!RetE)
+    return;
+
+  ProgramStateRef state = C.getState();
+  SymbolRef Sym =
+    state->getSValAsScalarOrLoc(RetE, C.getLocationContext()).getAsLocSymbol();
+  if (!Sym)
+    return;
+
+  // Get the reference count binding (if any).
+  const RefVal *T = state->get<RefBindings>(Sym);
+  if (!T)
+    return;
+
+  // Change the reference count.
+  RefVal X = *T;
+
+  switch (X.getKind()) {
+    case RefVal::Owned: {
+      unsigned cnt = X.getCount();
+      assert(cnt > 0);
+      X.setCount(cnt - 1);
+      X = X ^ RefVal::ReturnedOwned;
+      break;
+    }
+
+    case RefVal::NotOwned: {
+      unsigned cnt = X.getCount();
+      if (cnt) {
+        X.setCount(cnt - 1);
+        X = X ^ RefVal::ReturnedOwned;
+      }
+      else {
+        X = X ^ RefVal::ReturnedNotOwned;
+      }
+      break;
+    }
+
+    default:
+      return;
+  }
+
+  // Update the binding.
+  state = state->set<RefBindings>(Sym, X);
+  ExplodedNode *Pred = C.addTransition(state);
+
+  // At this point we have updated the state properly.
+  // Everything after this is merely checking to see if the return value has
+  // been over- or under-retained.
+
+  // Did we cache out?
+  if (!Pred)
+    return;
+
+  // Update the autorelease counts.
+  static SimpleProgramPointTag
+         AutoreleaseTag("RetainCountChecker : Autorelease");
+  GenericNodeBuilderRefCount Bd(C, &AutoreleaseTag);
+  llvm::tie(Pred, state) = handleAutoreleaseCounts(state, Bd, Pred, C, Sym, X);
+
+  // Did we cache out?
+  if (!Pred)
+    return;
+
+  // Get the updated binding.
+  T = state->get<RefBindings>(Sym);
+  assert(T);
+  X = *T;
+
+  // Consult the summary of the enclosing method.
+  RetainSummaryManager &Summaries = getSummaryManager(C);
+  const Decl *CD = &Pred->getCodeDecl();
+
+  if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CD)) {
+    // Unlike regular functions, /all/ ObjC methods are assumed to always
+    // follow Cocoa retain-count conventions, not just those with special
+    // names or attributes.
+    const RetainSummary *Summ = Summaries.getMethodSummary(MD);
+    RetEffect RE = Summ ? Summ->getRetEffect() : RetEffect::MakeNoRet();
+    checkReturnWithRetEffect(S, C, Pred, RE, X, Sym, state);
+  }
+
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) {
+    if (!isa<CXXMethodDecl>(FD))
+      if (const RetainSummary *Summ = Summaries.getSummary(FD))
+        checkReturnWithRetEffect(S, C, Pred, Summ->getRetEffect(), X,
+                                 Sym, state);
+  }
+}
+
+void RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S,
+                                                  CheckerContext &C,
+                                                  ExplodedNode *Pred,
+                                                  RetEffect RE, RefVal X,
+                                                  SymbolRef Sym,
+                                              ProgramStateRef state) const {
+  // Any leaks or other errors?
+  if (X.isReturnedOwned() && X.getCount() == 0) {
+    if (RE.getKind() != RetEffect::NoRet) {
+      bool hasError = false;
+      if (C.isObjCGCEnabled() && RE.getObjKind() == RetEffect::ObjC) {
+        // Things are more complicated with garbage collection.  If the
+        // returned object is suppose to be an Objective-C object, we have
+        // a leak (as the caller expects a GC'ed object) because no
+        // method should return ownership unless it returns a CF object.
+        hasError = true;
+        X = X ^ RefVal::ErrorGCLeakReturned;
+      }
+      else if (!RE.isOwned()) {
+        // Either we are using GC and the returned object is a CF type
+        // or we aren't using GC.  In either case, we expect that the
+        // enclosing method is expected to return ownership.
+        hasError = true;
+        X = X ^ RefVal::ErrorLeakReturned;
+      }
+
+      if (hasError) {
+        // Generate an error node.
+        state = state->set<RefBindings>(Sym, X);
+
+        static SimpleProgramPointTag
+               ReturnOwnLeakTag("RetainCountChecker : ReturnsOwnLeak");
+        ExplodedNode *N = C.addTransition(state, Pred, &ReturnOwnLeakTag);
+        if (N) {
+          const LangOptions &LOpts = C.getASTContext().getLangOpts();
+          bool GCEnabled = C.isObjCGCEnabled();
+          CFRefReport *report =
+            new CFRefLeakReport(*getLeakAtReturnBug(LOpts, GCEnabled),
+                                LOpts, GCEnabled, SummaryLog,
+                                N, Sym, C);
+          C.EmitReport(report);
+        }
+      }
+    }
+  } else if (X.isReturnedNotOwned()) {
+    if (RE.isOwned()) {
+      // Trying to return a not owned object to a caller expecting an
+      // owned object.
+      state = state->set<RefBindings>(Sym, X ^ RefVal::ErrorReturnedNotOwned);
+
+      static SimpleProgramPointTag
+             ReturnNotOwnedTag("RetainCountChecker : ReturnNotOwnedForOwned");
+      ExplodedNode *N = C.addTransition(state, Pred, &ReturnNotOwnedTag);
+      if (N) {
+        if (!returnNotOwnedForOwned)
+          returnNotOwnedForOwned.reset(new ReturnedNotOwnedForOwned());
+
+        CFRefReport *report =
+            new CFRefReport(*returnNotOwnedForOwned,
+                            C.getASTContext().getLangOpts(), 
+                            C.isObjCGCEnabled(), SummaryLog, N, Sym);
+        C.EmitReport(report);
+      }
+    }
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// Check various ways a symbol can be invalidated.
+//===----------------------------------------------------------------------===//
+
+void RetainCountChecker::checkBind(SVal loc, SVal val, const Stmt *S,
+                                   CheckerContext &C) const {
+  // Are we storing to something that causes the value to "escape"?
+  bool escapes = true;
+
+  // A value escapes in three possible cases (this may change):
+  //
+  // (1) we are binding to something that is not a memory region.
+  // (2) we are binding to a memregion that does not have stack storage
+  // (3) we are binding to a memregion with stack storage that the store
+  //     does not understand.
+  ProgramStateRef state = C.getState();
+
+  if (loc::MemRegionVal *regionLoc = dyn_cast<loc::MemRegionVal>(&loc)) {
+    escapes = !regionLoc->getRegion()->hasStackStorage();
+
+    if (!escapes) {
+      // To test (3), generate a new state with the binding added.  If it is
+      // the same state, then it escapes (since the store cannot represent
+      // the binding).
+      escapes = (state == (state->bindLoc(*regionLoc, val)));
+    }
+    if (!escapes) {
+      // Case 4: We do not currently model what happens when a symbol is
+      // assigned to a struct field, so be conservative here and let the symbol
+      // go. TODO: This could definitely be improved upon.
+      escapes = !isa<VarRegion>(regionLoc->getRegion());
+    }
+  }
+
+  // If our store can represent the binding and we aren't storing to something
+  // that doesn't have local storage then just return and have the simulation
+  // state continue as is.
+  if (!escapes)
+      return;
+
+  // Otherwise, find all symbols referenced by 'val' that we are tracking
+  // and stop tracking them.
+  state = state->scanReachableSymbols<StopTrackingCallback>(val).getState();
+  C.addTransition(state);
+}
+
+ProgramStateRef RetainCountChecker::evalAssume(ProgramStateRef state,
+                                                   SVal Cond,
+                                                   bool Assumption) const {
+
+  // FIXME: We may add to the interface of evalAssume the list of symbols
+  //  whose assumptions have changed.  For now we just iterate through the
+  //  bindings and check if any of the tracked symbols are NULL.  This isn't
+  //  too bad since the number of symbols we will track in practice are
+  //  probably small and evalAssume is only called at branches and a few
+  //  other places.
+  RefBindings B = state->get<RefBindings>();
+
+  if (B.isEmpty())
+    return state;
+
+  bool changed = false;
+  RefBindings::Factory &RefBFactory = state->get_context<RefBindings>();
+
+  for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
+    // Check if the symbol is null (or equal to any constant).
+    // If this is the case, stop tracking the symbol.
+    if (state->getSymVal(I.getKey())) {
+      changed = true;
+      B = RefBFactory.remove(B, I.getKey());
+    }
+  }
+
+  if (changed)
+    state = state->set<RefBindings>(B);
+
+  return state;
+}
+
+ProgramStateRef 
+RetainCountChecker::checkRegionChanges(ProgramStateRef state,
+                            const StoreManager::InvalidatedSymbols *invalidated,
+                                    ArrayRef<const MemRegion *> ExplicitRegions,
+                                    ArrayRef<const MemRegion *> Regions,
+                                    const CallOrObjCMessage *Call) const {
+  if (!invalidated)
+    return state;
+
+  llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols;
+  for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(),
+       E = ExplicitRegions.end(); I != E; ++I) {
+    if (const SymbolicRegion *SR = (*I)->StripCasts()->getAs<SymbolicRegion>())
+      WhitelistedSymbols.insert(SR->getSymbol());
+  }
+
+  for (StoreManager::InvalidatedSymbols::const_iterator I=invalidated->begin(),
+       E = invalidated->end(); I!=E; ++I) {
+    SymbolRef sym = *I;
+    if (WhitelistedSymbols.count(sym))
+      continue;
+    // Remove any existing reference-count binding.
+    state = state->remove<RefBindings>(sym);
+  }
+  return state;
+}
+
+//===----------------------------------------------------------------------===//
+// Handle dead symbols and end-of-path.
+//===----------------------------------------------------------------------===//
+
+std::pair<ExplodedNode *, ProgramStateRef >
+RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state, 
+                                            GenericNodeBuilderRefCount Bd,
+                                            ExplodedNode *Pred,
+                                            CheckerContext &Ctx,
+                                            SymbolRef Sym, RefVal V) const {
+  unsigned ACnt = V.getAutoreleaseCount();
+
+  // No autorelease counts?  Nothing to be done.
+  if (!ACnt)
+    return std::make_pair(Pred, state);
+
+  assert(!Ctx.isObjCGCEnabled() && "Autorelease counts in GC mode?");
+  unsigned Cnt = V.getCount();
+
+  // FIXME: Handle sending 'autorelease' to already released object.
+
+  if (V.getKind() == RefVal::ReturnedOwned)
+    ++Cnt;
+
+  if (ACnt <= Cnt) {
+    if (ACnt == Cnt) {
+      V.clearCounts();
+      if (V.getKind() == RefVal::ReturnedOwned)
+        V = V ^ RefVal::ReturnedNotOwned;
+      else
+        V = V ^ RefVal::NotOwned;
+    } else {
+      V.setCount(Cnt - ACnt);
+      V.setAutoreleaseCount(0);
+    }
+    state = state->set<RefBindings>(Sym, V);
+    ExplodedNode *N = Bd.MakeNode(state, Pred);
+    if (N == 0)
+      state = 0;
+    return std::make_pair(N, state);
+  }
+
+  // Woah!  More autorelease counts then retain counts left.
+  // Emit hard error.
+  V = V ^ RefVal::ErrorOverAutorelease;
+  state = state->set<RefBindings>(Sym, V);
+
+  if (ExplodedNode *N = Bd.MakeNode(state, Pred, true)) {
+    SmallString<128> sbuf;
+    llvm::raw_svector_ostream os(sbuf);
+    os << "Object over-autoreleased: object was sent -autorelease ";
+    if (V.getAutoreleaseCount() > 1)
+      os << V.getAutoreleaseCount() << " times ";
+    os << "but the object has a +" << V.getCount() << " retain count";
+
+    if (!overAutorelease)
+      overAutorelease.reset(new OverAutorelease());
+
+    const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
+    CFRefReport *report =
+      new CFRefReport(*overAutorelease, LOpts, /* GCEnabled = */ false,
+                      SummaryLog, N, Sym, os.str());
+    Ctx.EmitReport(report);
+  }
+
+  return std::make_pair((ExplodedNode *)0, (ProgramStateRef )0);
+}
+
+ProgramStateRef 
+RetainCountChecker::handleSymbolDeath(ProgramStateRef state,
+                                      SymbolRef sid, RefVal V,
+                                    SmallVectorImpl<SymbolRef> &Leaked) const {
+  bool hasLeak = false;
+  if (V.isOwned())
+    hasLeak = true;
+  else if (V.isNotOwned() || V.isReturnedOwned())
+    hasLeak = (V.getCount() > 0);
+
+  if (!hasLeak)
+    return state->remove<RefBindings>(sid);
+
+  Leaked.push_back(sid);
+  return state->set<RefBindings>(sid, V ^ RefVal::ErrorLeak);
+}
+
+ExplodedNode *
+RetainCountChecker::processLeaks(ProgramStateRef state,
+                                 SmallVectorImpl<SymbolRef> &Leaked,
+                                 GenericNodeBuilderRefCount &Builder,
+                                 CheckerContext &Ctx,
+                                 ExplodedNode *Pred) const {
+  if (Leaked.empty())
+    return Pred;
+
+  // Generate an intermediate node representing the leak point.
+  ExplodedNode *N = Builder.MakeNode(state, Pred);
+
+  if (N) {
+    for (SmallVectorImpl<SymbolRef>::iterator
+         I = Leaked.begin(), E = Leaked.end(); I != E; ++I) {
+
+      const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
+      bool GCEnabled = Ctx.isObjCGCEnabled();
+      CFRefBug *BT = Pred ? getLeakWithinFunctionBug(LOpts, GCEnabled)
+                          : getLeakAtReturnBug(LOpts, GCEnabled);
+      assert(BT && "BugType not initialized.");
+
+      CFRefLeakReport *report = new CFRefLeakReport(*BT, LOpts, GCEnabled, 
+                                                    SummaryLog, N, *I, Ctx);
+      Ctx.EmitReport(report);
+    }
+  }
+
+  return N;
+}
+
+void RetainCountChecker::checkEndPath(CheckerContext &Ctx) const {
+  ProgramStateRef state = Ctx.getState();
+  GenericNodeBuilderRefCount Bd(Ctx);
+  RefBindings B = state->get<RefBindings>();
+  ExplodedNode *Pred = Ctx.getPredecessor();
+
+  for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
+    llvm::tie(Pred, state) = handleAutoreleaseCounts(state, Bd, Pred, Ctx,
+                                                     I->first, I->second);
+    if (!state)
+      return;
+  }
+
+  // If the current LocationContext has a parent, don't check for leaks.
+  // We will do that later.
+  // FIXME: we should instead check for imblances of the retain/releases,
+  // and suggest annotations.
+  if (Ctx.getLocationContext()->getParent())
+    return;
+  
+  B = state->get<RefBindings>();
+  SmallVector<SymbolRef, 10> Leaked;
+
+  for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I)
+    state = handleSymbolDeath(state, I->first, I->second, Leaked);
+
+  processLeaks(state, Leaked, Bd, Ctx, Pred);
+}
+
+const ProgramPointTag *
+RetainCountChecker::getDeadSymbolTag(SymbolRef sym) const {
+  const SimpleProgramPointTag *&tag = DeadSymbolTags[sym];
+  if (!tag) {
+    SmallString<64> buf;
+    llvm::raw_svector_ostream out(buf);
+    out << "RetainCountChecker : Dead Symbol : ";
+    sym->dumpToStream(out);
+    tag = new SimpleProgramPointTag(out.str());
+  }
+  return tag;  
+}
+
+void RetainCountChecker::checkDeadSymbols(SymbolReaper &SymReaper,
+                                          CheckerContext &C) const {
+  ExplodedNode *Pred = C.getPredecessor();
+
+  ProgramStateRef state = C.getState();
+  RefBindings B = state->get<RefBindings>();
+
+  // Update counts from autorelease pools
+  for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
+       E = SymReaper.dead_end(); I != E; ++I) {
+    SymbolRef Sym = *I;
+    if (const RefVal *T = B.lookup(Sym)){
+      // Use the symbol as the tag.
+      // FIXME: This might not be as unique as we would like.
+      GenericNodeBuilderRefCount Bd(C, getDeadSymbolTag(Sym));
+      llvm::tie(Pred, state) = handleAutoreleaseCounts(state, Bd, Pred, C,
+                                                       Sym, *T);
+      if (!state)
+        return;
+    }
+  }
+
+  B = state->get<RefBindings>();
+  SmallVector<SymbolRef, 10> Leaked;
+
+  for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
+       E = SymReaper.dead_end(); I != E; ++I) {
+    if (const RefVal *T = B.lookup(*I))
+      state = handleSymbolDeath(state, *I, *T, Leaked);
+  }
+
+  {
+    GenericNodeBuilderRefCount Bd(C, this);
+    Pred = processLeaks(state, Leaked, Bd, C, Pred);
+  }
+
+  // Did we cache out?
+  if (!Pred)
+    return;
+
+  // Now generate a new node that nukes the old bindings.
+  RefBindings::Factory &F = state->get_context<RefBindings>();
+
+  for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
+       E = SymReaper.dead_end(); I != E; ++I)
+    B = F.remove(B, *I);
+
+  state = state->set<RefBindings>(B);
+  C.addTransition(state, Pred);
+}
+
+//===----------------------------------------------------------------------===//
+// Debug printing of refcount bindings and autorelease pools.
+//===----------------------------------------------------------------------===//
+
+static void PrintPool(raw_ostream &Out, SymbolRef Sym,
+                      ProgramStateRef State) {
+  Out << ' ';
+  if (Sym)
+    Sym->dumpToStream(Out);
+  else
+    Out << "<pool>";
+  Out << ":{";
+
+  // Get the contents of the pool.
+  if (const ARCounts *Cnts = State->get<AutoreleasePoolContents>(Sym))
+    for (ARCounts::iterator I = Cnts->begin(), E = Cnts->end(); I != E; ++I)
+      Out << '(' << I.getKey() << ',' << I.getData() << ')';
+
+  Out << '}';
+}
+
+static bool UsesAutorelease(ProgramStateRef state) {
+  // A state uses autorelease if it allocated an autorelease pool or if it has
+  // objects in the caller's autorelease pool.
+  return !state->get<AutoreleaseStack>().isEmpty() ||
+          state->get<AutoreleasePoolContents>(SymbolRef());
+}
+
+void RetainCountChecker::printState(raw_ostream &Out, ProgramStateRef State,
+                                    const char *NL, const char *Sep) const {
+
+  RefBindings B = State->get<RefBindings>();
+
+  if (!B.isEmpty())
+    Out << Sep << NL;
+
+  for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
+    Out << I->first << " : ";
+    I->second.print(Out);
+    Out << NL;
+  }
+
+  // Print the autorelease stack.
+  if (UsesAutorelease(State)) {
+    Out << Sep << NL << "AR pool stack:";
+    ARStack Stack = State->get<AutoreleaseStack>();
+
+    PrintPool(Out, SymbolRef(), State);  // Print the caller's pool.
+    for (ARStack::iterator I = Stack.begin(), E = Stack.end(); I != E; ++I)
+      PrintPool(Out, *I, State);
+
+    Out << NL;
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// Checker registration.
+//===----------------------------------------------------------------------===//
+
+void ento::registerRetainCountChecker(CheckerManager &Mgr) {
+  Mgr.registerChecker<RetainCountChecker>();
+}
+
diff --git a/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
new file mode 100644
index 0000000..6e56593
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
@@ -0,0 +1,91 @@
+//== ReturnPointerRangeChecker.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 ReturnPointerRangeChecker, which is a path-sensitive check
+// which looks for an out-of-bound pointer being returned to callers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class ReturnPointerRangeChecker : 
+    public Checker< check::PreStmt<ReturnStmt> > {
+  mutable OwningPtr<BuiltinBug> BT;
+public:
+    void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const;
+};
+}
+
+void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS,
+                                             CheckerContext &C) const {
+  ProgramStateRef state = C.getState();
+
+  const Expr *RetE = RS->getRetValue();
+  if (!RetE)
+    return;
+ 
+  SVal V = state->getSVal(RetE, C.getLocationContext());
+  const MemRegion *R = V.getAsRegion();
+
+  const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(R);
+  if (!ER)
+    return;
+
+  DefinedOrUnknownSVal Idx = cast<DefinedOrUnknownSVal>(ER->getIndex());
+  // Zero index is always in bound, this also passes ElementRegions created for
+  // pointer casts.
+  if (Idx.isZeroConstant())
+    return;
+  // FIXME: All of this out-of-bounds checking should eventually be refactored
+  // into a common place.
+
+  DefinedOrUnknownSVal NumElements
+    = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(),
+                                           ER->getValueType());
+
+  ProgramStateRef StInBound = state->assumeInBound(Idx, NumElements, true);
+  ProgramStateRef StOutBound = state->assumeInBound(Idx, NumElements, false);
+  if (StOutBound && !StInBound) {
+    ExplodedNode *N = C.generateSink(StOutBound);
+
+    if (!N)
+      return;
+  
+    // FIXME: This bug correspond to CWE-466.  Eventually we should have bug
+    // types explicitly reference such exploit categories (when applicable).
+    if (!BT)
+      BT.reset(new BuiltinBug("Return of pointer value outside of expected range",
+           "Returned pointer value points outside the original object "
+           "(potential buffer overflow)"));
+
+    // FIXME: It would be nice to eventually make this diagnostic more clear,
+    // e.g., by referencing the original declaration or by saying *why* this
+    // reference is outside the range.
+
+    // Generate a report for this bug.
+    BugReport *report = 
+      new BugReport(*BT, BT->getDescription(), N);
+
+    report->addRange(RetE->getSourceRange());
+    C.EmitReport(report);
+  }
+}
+
+void ento::registerReturnPointerRangeChecker(CheckerManager &mgr) {
+  mgr.registerChecker<ReturnPointerRangeChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
new file mode 100644
index 0000000..7b1f0b1
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
@@ -0,0 +1,65 @@
+//== ReturnUndefChecker.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 ReturnUndefChecker, which is a path-sensitive
+// check which looks for undefined or garbage values being returned to the
+// caller.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class ReturnUndefChecker : 
+    public Checker< check::PreStmt<ReturnStmt> > {
+  mutable OwningPtr<BuiltinBug> BT;
+public:
+  void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const;
+};
+}
+
+void ReturnUndefChecker::checkPreStmt(const ReturnStmt *RS,
+                                      CheckerContext &C) const {
+ 
+  const Expr *RetE = RS->getRetValue();
+  if (!RetE)
+    return;
+  
+  if (!C.getState()->getSVal(RetE, C.getLocationContext()).isUndef())
+    return;
+  
+  ExplodedNode *N = C.generateSink();
+
+  if (!N)
+    return;
+  
+  if (!BT)
+    BT.reset(new BuiltinBug("Garbage return value",
+                            "Undefined or garbage value returned to caller"));
+    
+  BugReport *report = 
+    new BugReport(*BT, BT->getDescription(), N);
+
+  report->addRange(RetE->getSourceRange());
+  report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, RetE,
+                                                                  report));
+
+  C.EmitReport(report);
+}
+
+void ento::registerReturnUndefChecker(CheckerManager &mgr) {
+  mgr.registerChecker<ReturnUndefChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
new file mode 100644
index 0000000..54cf569
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
@@ -0,0 +1,230 @@
+//=== StackAddrEscapeChecker.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 stack address leak checker, which checks if an invalid 
+// stack address is stored into a global or heap location. See CERT DCL30-C.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/SmallString.h"
+using namespace clang;
+using namespace ento;
+
+namespace {
+class StackAddrEscapeChecker : public Checker< check::PreStmt<ReturnStmt>,
+                                               check::EndPath > {
+  mutable OwningPtr<BuiltinBug> BT_stackleak;
+  mutable OwningPtr<BuiltinBug> BT_returnstack;
+
+public:
+  void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const;
+  void checkEndPath(CheckerContext &Ctx) const;
+private:
+  void EmitStackError(CheckerContext &C, const MemRegion *R,
+                      const Expr *RetE) const;
+  static SourceRange GenName(raw_ostream &os, const MemRegion *R,
+                             SourceManager &SM);
+};
+}
+
+SourceRange StackAddrEscapeChecker::GenName(raw_ostream &os,
+                                          const MemRegion *R,
+                                          SourceManager &SM) {
+    // Get the base region, stripping away fields and elements.
+  R = R->getBaseRegion();
+  SourceRange range;
+  os << "Address of ";
+  
+  // Check if the region is a compound literal.
+  if (const CompoundLiteralRegion* CR = dyn_cast<CompoundLiteralRegion>(R)) { 
+    const CompoundLiteralExpr *CL = CR->getLiteralExpr();
+    os << "stack memory associated with a compound literal "
+          "declared on line "
+        << SM.getExpansionLineNumber(CL->getLocStart())
+        << " returned to caller";    
+    range = CL->getSourceRange();
+  }
+  else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(R)) {
+    const Expr *ARE = AR->getExpr();
+    SourceLocation L = ARE->getLocStart();
+    range = ARE->getSourceRange();    
+    os << "stack memory allocated by call to alloca() on line "
+       << SM.getExpansionLineNumber(L);
+  }
+  else if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(R)) {
+    const BlockDecl *BD = BR->getCodeRegion()->getDecl();
+    SourceLocation L = BD->getLocStart();
+    range = BD->getSourceRange();
+    os << "stack-allocated block declared on line "
+       << SM.getExpansionLineNumber(L);
+  }
+  else if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
+    os << "stack memory associated with local variable '"
+       << VR->getString() << '\'';
+    range = VR->getDecl()->getSourceRange();
+  }
+  else if (const CXXTempObjectRegion *TOR = dyn_cast<CXXTempObjectRegion>(R)) {
+    os << "stack memory associated with temporary object of type '"
+       << TOR->getValueType().getAsString() << '\'';
+    range = TOR->getExpr()->getSourceRange();
+  }
+  else {
+    llvm_unreachable("Invalid region in ReturnStackAddressChecker.");
+  } 
+  
+  return range;
+}
+
+void StackAddrEscapeChecker::EmitStackError(CheckerContext &C, const MemRegion *R,
+                                          const Expr *RetE) const {
+  ExplodedNode *N = C.generateSink();
+
+  if (!N)
+    return;
+
+  if (!BT_returnstack)
+   BT_returnstack.reset(
+                 new BuiltinBug("Return of address to stack-allocated memory"));
+
+  // Generate a report for this bug.
+  SmallString<512> buf;
+  llvm::raw_svector_ostream os(buf);
+  SourceRange range = GenName(os, R, C.getSourceManager());
+  os << " returned to caller";
+  BugReport *report = new BugReport(*BT_returnstack, os.str(), N);
+  report->addRange(RetE->getSourceRange());
+  if (range.isValid())
+    report->addRange(range);
+
+  C.EmitReport(report);
+}
+
+void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS,
+                                          CheckerContext &C) const {
+  
+  const Expr *RetE = RS->getRetValue();
+  if (!RetE)
+    return;
+ 
+  SVal V = C.getState()->getSVal(RetE, C.getLocationContext());
+  const MemRegion *R = V.getAsRegion();
+
+  if (!R)
+    return;
+  
+  const StackSpaceRegion *SS =
+    dyn_cast_or_null<StackSpaceRegion>(R->getMemorySpace());
+    
+  if (!SS)
+    return;
+
+  // Return stack memory in an ancestor stack frame is fine.
+  const StackFrameContext *SFC = SS->getStackFrame();
+  if (SFC != C.getLocationContext()->getCurrentStackFrame())
+    return;
+
+  // Automatic reference counting automatically copies blocks.
+  if (C.getASTContext().getLangOpts().ObjCAutoRefCount &&
+      isa<BlockDataRegion>(R))
+    return;
+
+  EmitStackError(C, R, RetE);
+}
+
+void StackAddrEscapeChecker::checkEndPath(CheckerContext &Ctx) const {
+  ProgramStateRef state = Ctx.getState();
+
+  // Iterate over all bindings to global variables and see if it contains
+  // a memory region in the stack space.
+  class CallBack : public StoreManager::BindingsHandler {
+  private:
+    CheckerContext &Ctx;
+    const StackFrameContext *CurSFC;
+  public:
+    SmallVector<std::pair<const MemRegion*, const MemRegion*>, 10> V;
+
+    CallBack(CheckerContext &CC) :
+      Ctx(CC),
+      CurSFC(CC.getLocationContext()->getCurrentStackFrame())
+    {}
+    
+    bool HandleBinding(StoreManager &SMgr, Store store,
+                       const MemRegion *region, SVal val) {
+      
+      if (!isa<GlobalsSpaceRegion>(region->getMemorySpace()))
+        return true;
+      
+      const MemRegion *vR = val.getAsRegion();
+      if (!vR)
+        return true;
+        
+      // Under automated retain release, it is okay to assign a block
+      // directly to a global variable.
+      if (Ctx.getASTContext().getLangOpts().ObjCAutoRefCount &&
+          isa<BlockDataRegion>(vR))
+        return true;
+
+      if (const StackSpaceRegion *SSR = 
+          dyn_cast<StackSpaceRegion>(vR->getMemorySpace())) {
+        // If the global variable holds a location in the current stack frame,
+        // record the binding to emit a warning.
+        if (SSR->getStackFrame() == CurSFC)
+          V.push_back(std::make_pair(region, vR));
+      }
+      
+      return true;
+    }
+  };
+    
+  CallBack cb(Ctx);
+  state->getStateManager().getStoreManager().iterBindings(state->getStore(),cb);
+
+  if (cb.V.empty())
+    return;
+
+  // Generate an error node.
+  ExplodedNode *N = Ctx.addTransition(state);
+  if (!N)
+    return;
+
+  if (!BT_stackleak)
+    BT_stackleak.reset(
+      new BuiltinBug("Stack address stored into global variable",
+                     "Stack address was saved into a global variable. "
+                     "This is dangerous because the address will become "
+                     "invalid after returning from the function"));
+  
+  for (unsigned i = 0, e = cb.V.size(); i != e; ++i) {
+    // Generate a report for this bug.
+    SmallString<512> buf;
+    llvm::raw_svector_ostream os(buf);
+    SourceRange range = GenName(os, cb.V[i].second,
+                                Ctx.getSourceManager());
+    os << " is still referred to by the global variable '";
+    const VarRegion *VR = cast<VarRegion>(cb.V[i].first->getBaseRegion());
+    os << *VR->getDecl()
+       << "' upon returning to the caller.  This will be a dangling reference";
+    BugReport *report = new BugReport(*BT_stackleak, os.str(), N);
+    if (range.isValid())
+      report->addRange(range);
+
+    Ctx.EmitReport(report);
+  }
+}
+
+void ento::registerStackAddrEscapeChecker(CheckerManager &mgr) {
+  mgr.registerChecker<StackAddrEscapeChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
new file mode 100644
index 0000000..3745d4a
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -0,0 +1,475 @@
+//===-- StreamChecker.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 checkers that model and check stream handling functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/ImmutableMap.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+struct StreamState {
+  enum Kind { Opened, Closed, OpenFailed, Escaped } K;
+  const Stmt *S;
+
+  StreamState(Kind k, const Stmt *s) : K(k), S(s) {}
+
+  bool isOpened() const { return K == Opened; }
+  bool isClosed() const { return K == Closed; }
+  //bool isOpenFailed() const { return K == OpenFailed; }
+  //bool isEscaped() const { return K == Escaped; }
+
+  bool operator==(const StreamState &X) const {
+    return K == X.K && S == X.S;
+  }
+
+  static StreamState getOpened(const Stmt *s) { return StreamState(Opened, s); }
+  static StreamState getClosed(const Stmt *s) { return StreamState(Closed, s); }
+  static StreamState getOpenFailed(const Stmt *s) { 
+    return StreamState(OpenFailed, s); 
+  }
+  static StreamState getEscaped(const Stmt *s) {
+    return StreamState(Escaped, s);
+  }
+
+  void Profile(llvm::FoldingSetNodeID &ID) const {
+    ID.AddInteger(K);
+    ID.AddPointer(S);
+  }
+};
+
+class StreamChecker : public Checker<eval::Call,
+                                       check::DeadSymbols,
+                                       check::EndPath,
+                                       check::PreStmt<ReturnStmt> > {
+  mutable IdentifierInfo *II_fopen, *II_tmpfile, *II_fclose, *II_fread,
+                 *II_fwrite, 
+                 *II_fseek, *II_ftell, *II_rewind, *II_fgetpos, *II_fsetpos,  
+                 *II_clearerr, *II_feof, *II_ferror, *II_fileno;
+  mutable OwningPtr<BuiltinBug> BT_nullfp, BT_illegalwhence,
+                                      BT_doubleclose, BT_ResourceLeak;
+
+public:
+  StreamChecker() 
+    : II_fopen(0), II_tmpfile(0) ,II_fclose(0), II_fread(0), II_fwrite(0), 
+      II_fseek(0), II_ftell(0), II_rewind(0), II_fgetpos(0), II_fsetpos(0), 
+      II_clearerr(0), II_feof(0), II_ferror(0), II_fileno(0) {}
+
+  bool evalCall(const CallExpr *CE, CheckerContext &C) const;
+  void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
+  void checkEndPath(CheckerContext &Ctx) const;
+  void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
+
+private:
+  void Fopen(CheckerContext &C, const CallExpr *CE) const;
+  void Tmpfile(CheckerContext &C, const CallExpr *CE) const;
+  void Fclose(CheckerContext &C, const CallExpr *CE) const;
+  void Fread(CheckerContext &C, const CallExpr *CE) const;
+  void Fwrite(CheckerContext &C, const CallExpr *CE) const;
+  void Fseek(CheckerContext &C, const CallExpr *CE) const;
+  void Ftell(CheckerContext &C, const CallExpr *CE) const;
+  void Rewind(CheckerContext &C, const CallExpr *CE) const;
+  void Fgetpos(CheckerContext &C, const CallExpr *CE) const;
+  void Fsetpos(CheckerContext &C, const CallExpr *CE) const;
+  void Clearerr(CheckerContext &C, const CallExpr *CE) const;
+  void Feof(CheckerContext &C, const CallExpr *CE) const;
+  void Ferror(CheckerContext &C, const CallExpr *CE) const;
+  void Fileno(CheckerContext &C, const CallExpr *CE) const;
+
+  void OpenFileAux(CheckerContext &C, const CallExpr *CE) const;
+  
+  ProgramStateRef CheckNullStream(SVal SV, ProgramStateRef state, 
+                                 CheckerContext &C) const;
+  ProgramStateRef CheckDoubleClose(const CallExpr *CE, ProgramStateRef state, 
+                                 CheckerContext &C) const;
+};
+
+} // end anonymous namespace
+
+namespace clang {
+namespace ento {
+  template <>
+  struct ProgramStateTrait<StreamState> 
+    : public ProgramStatePartialTrait<llvm::ImmutableMap<SymbolRef, StreamState> > {
+    static void *GDMIndex() { static int x; return &x; }
+  };
+}
+}
+
+bool StreamChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
+  const FunctionDecl *FD = C.getCalleeDecl(CE);
+  if (!FD)
+    return false;
+
+  ASTContext &Ctx = C.getASTContext();
+  if (!II_fopen)
+    II_fopen = &Ctx.Idents.get("fopen");
+  if (!II_tmpfile)
+    II_tmpfile = &Ctx.Idents.get("tmpfile");
+  if (!II_fclose)
+    II_fclose = &Ctx.Idents.get("fclose");
+  if (!II_fread)
+    II_fread = &Ctx.Idents.get("fread");
+  if (!II_fwrite)
+    II_fwrite = &Ctx.Idents.get("fwrite");
+  if (!II_fseek)
+    II_fseek = &Ctx.Idents.get("fseek");
+  if (!II_ftell)
+    II_ftell = &Ctx.Idents.get("ftell");
+  if (!II_rewind)
+    II_rewind = &Ctx.Idents.get("rewind");
+  if (!II_fgetpos)
+    II_fgetpos = &Ctx.Idents.get("fgetpos");
+  if (!II_fsetpos)
+    II_fsetpos = &Ctx.Idents.get("fsetpos");
+  if (!II_clearerr)
+    II_clearerr = &Ctx.Idents.get("clearerr");
+  if (!II_feof)
+    II_feof = &Ctx.Idents.get("feof");
+  if (!II_ferror)
+    II_ferror = &Ctx.Idents.get("ferror");
+  if (!II_fileno)
+    II_fileno = &Ctx.Idents.get("fileno");
+
+  if (FD->getIdentifier() == II_fopen) {
+    Fopen(C, CE);
+    return true;
+  }
+  if (FD->getIdentifier() == II_tmpfile) {
+    Tmpfile(C, CE);
+    return true;
+  }
+  if (FD->getIdentifier() == II_fclose) {
+    Fclose(C, CE);
+    return true;
+  }
+  if (FD->getIdentifier() == II_fread) {
+    Fread(C, CE);
+    return true;
+  }
+  if (FD->getIdentifier() == II_fwrite) {
+    Fwrite(C, CE);
+    return true;
+  }
+  if (FD->getIdentifier() == II_fseek) {
+    Fseek(C, CE);
+    return true;
+  }
+  if (FD->getIdentifier() == II_ftell) {
+    Ftell(C, CE);
+    return true;
+  }
+  if (FD->getIdentifier() == II_rewind) {
+    Rewind(C, CE);
+    return true;
+  }
+  if (FD->getIdentifier() == II_fgetpos) {
+    Fgetpos(C, CE);
+    return true;
+  }
+  if (FD->getIdentifier() == II_fsetpos) {
+    Fsetpos(C, CE);
+    return true;
+  }
+  if (FD->getIdentifier() == II_clearerr) {
+    Clearerr(C, CE);
+    return true;
+  }
+  if (FD->getIdentifier() == II_feof) {
+    Feof(C, CE);
+    return true;
+  }
+  if (FD->getIdentifier() == II_ferror) {
+    Ferror(C, CE);
+    return true;
+  }
+  if (FD->getIdentifier() == II_fileno) {
+    Fileno(C, CE);
+    return true;
+  }
+
+  return false;
+}
+
+void StreamChecker::Fopen(CheckerContext &C, const CallExpr *CE) const {
+  OpenFileAux(C, CE);
+}
+
+void StreamChecker::Tmpfile(CheckerContext &C, const CallExpr *CE) const {
+  OpenFileAux(C, CE);
+}
+
+void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) const {
+  ProgramStateRef state = C.getState();
+  unsigned Count = C.getCurrentBlockCount();
+  SValBuilder &svalBuilder = C.getSValBuilder();
+  const LocationContext *LCtx = C.getPredecessor()->getLocationContext();
+  DefinedSVal RetVal =
+    cast<DefinedSVal>(svalBuilder.getConjuredSymbolVal(0, CE, LCtx, Count));
+  state = state->BindExpr(CE, C.getLocationContext(), RetVal);
+  
+  ConstraintManager &CM = C.getConstraintManager();
+  // Bifurcate the state into two: one with a valid FILE* pointer, the other
+  // with a NULL.
+  ProgramStateRef stateNotNull, stateNull;
+  llvm::tie(stateNotNull, stateNull) = CM.assumeDual(state, RetVal);
+  
+  if (SymbolRef Sym = RetVal.getAsSymbol()) {
+    // if RetVal is not NULL, set the symbol's state to Opened.
+    stateNotNull =
+      stateNotNull->set<StreamState>(Sym,StreamState::getOpened(CE));
+    stateNull =
+      stateNull->set<StreamState>(Sym, StreamState::getOpenFailed(CE));
+
+    C.addTransition(stateNotNull);
+    C.addTransition(stateNull);
+  }
+}
+
+void StreamChecker::Fclose(CheckerContext &C, const CallExpr *CE) const {
+  ProgramStateRef state = CheckDoubleClose(CE, C.getState(), C);
+  if (state)
+    C.addTransition(state);
+}
+
+void StreamChecker::Fread(CheckerContext &C, const CallExpr *CE) const {
+  ProgramStateRef state = C.getState();
+  if (!CheckNullStream(state->getSVal(CE->getArg(3), C.getLocationContext()),
+                       state, C))
+    return;
+}
+
+void StreamChecker::Fwrite(CheckerContext &C, const CallExpr *CE) const {
+  ProgramStateRef state = C.getState();
+  if (!CheckNullStream(state->getSVal(CE->getArg(3), C.getLocationContext()),
+                       state, C))
+    return;
+}
+
+void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) const {
+  ProgramStateRef state = C.getState();
+  if (!(state = CheckNullStream(state->getSVal(CE->getArg(0),
+                                               C.getLocationContext()), state, C)))
+    return;
+  // Check the legality of the 'whence' argument of 'fseek'.
+  SVal Whence = state->getSVal(CE->getArg(2), C.getLocationContext());
+  const nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&Whence);
+
+  if (!CI)
+    return;
+
+  int64_t x = CI->getValue().getSExtValue();
+  if (x >= 0 && x <= 2)
+    return;
+
+  if (ExplodedNode *N = C.addTransition(state)) {
+    if (!BT_illegalwhence)
+      BT_illegalwhence.reset(new BuiltinBug("Illegal whence argument",
+					"The whence argument to fseek() should be "
+					"SEEK_SET, SEEK_END, or SEEK_CUR."));
+    BugReport *R = new BugReport(*BT_illegalwhence, 
+				 BT_illegalwhence->getDescription(), N);
+    C.EmitReport(R);
+  }
+}
+
+void StreamChecker::Ftell(CheckerContext &C, const CallExpr *CE) const {
+  ProgramStateRef state = C.getState();
+  if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
+                       state, C))
+    return;
+}
+
+void StreamChecker::Rewind(CheckerContext &C, const CallExpr *CE) const {
+  ProgramStateRef state = C.getState();
+  if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
+                       state, C))
+    return;
+}
+
+void StreamChecker::Fgetpos(CheckerContext &C, const CallExpr *CE) const {
+  ProgramStateRef state = C.getState();
+  if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
+                       state, C))
+    return;
+}
+
+void StreamChecker::Fsetpos(CheckerContext &C, const CallExpr *CE) const {
+  ProgramStateRef state = C.getState();
+  if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
+                       state, C))
+    return;
+}
+
+void StreamChecker::Clearerr(CheckerContext &C, const CallExpr *CE) const {
+  ProgramStateRef state = C.getState();
+  if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
+                       state, C))
+    return;
+}
+
+void StreamChecker::Feof(CheckerContext &C, const CallExpr *CE) const {
+  ProgramStateRef state = C.getState();
+  if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
+                       state, C))
+    return;
+}
+
+void StreamChecker::Ferror(CheckerContext &C, const CallExpr *CE) const {
+  ProgramStateRef state = C.getState();
+  if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
+                       state, C))
+    return;
+}
+
+void StreamChecker::Fileno(CheckerContext &C, const CallExpr *CE) const {
+  ProgramStateRef state = C.getState();
+  if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
+                       state, C))
+    return;
+}
+
+ProgramStateRef StreamChecker::CheckNullStream(SVal SV, ProgramStateRef state,
+                                    CheckerContext &C) const {
+  const DefinedSVal *DV = dyn_cast<DefinedSVal>(&SV);
+  if (!DV)
+    return 0;
+
+  ConstraintManager &CM = C.getConstraintManager();
+  ProgramStateRef stateNotNull, stateNull;
+  llvm::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV);
+
+  if (!stateNotNull && stateNull) {
+    if (ExplodedNode *N = C.generateSink(stateNull)) {
+      if (!BT_nullfp)
+        BT_nullfp.reset(new BuiltinBug("NULL stream pointer",
+                                     "Stream pointer might be NULL."));
+      BugReport *R =new BugReport(*BT_nullfp, BT_nullfp->getDescription(), N);
+      C.EmitReport(R);
+    }
+    return 0;
+  }
+  return stateNotNull;
+}
+
+ProgramStateRef StreamChecker::CheckDoubleClose(const CallExpr *CE,
+                                               ProgramStateRef state,
+                                               CheckerContext &C) const {
+  SymbolRef Sym =
+    state->getSVal(CE->getArg(0), C.getLocationContext()).getAsSymbol();
+  if (!Sym)
+    return state;
+  
+  const StreamState *SS = state->get<StreamState>(Sym);
+
+  // If the file stream is not tracked, return.
+  if (!SS)
+    return state;
+  
+  // Check: Double close a File Descriptor could cause undefined behaviour.
+  // Conforming to man-pages
+  if (SS->isClosed()) {
+    ExplodedNode *N = C.generateSink();
+    if (N) {
+      if (!BT_doubleclose)
+        BT_doubleclose.reset(new BuiltinBug("Double fclose",
+                                        "Try to close a file Descriptor already"
+                                        " closed. Cause undefined behaviour."));
+      BugReport *R = new BugReport(*BT_doubleclose,
+                                   BT_doubleclose->getDescription(), N);
+      C.EmitReport(R);
+    }
+    return NULL;
+  }
+  
+  // Close the File Descriptor.
+  return state->set<StreamState>(Sym, StreamState::getClosed(CE));
+}
+
+void StreamChecker::checkDeadSymbols(SymbolReaper &SymReaper,
+                                     CheckerContext &C) const {
+  for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
+         E = SymReaper.dead_end(); I != E; ++I) {
+    SymbolRef Sym = *I;
+    ProgramStateRef state = C.getState();
+    const StreamState *SS = state->get<StreamState>(Sym);
+    if (!SS)
+      return;
+
+    if (SS->isOpened()) {
+      ExplodedNode *N = C.generateSink();
+      if (N) {
+        if (!BT_ResourceLeak)
+          BT_ResourceLeak.reset(new BuiltinBug("Resource Leak", 
+                         "Opened File never closed. Potential Resource leak."));
+        BugReport *R = new BugReport(*BT_ResourceLeak, 
+                                     BT_ResourceLeak->getDescription(), N);
+        C.EmitReport(R);
+      }
+    }
+  }
+}
+
+void StreamChecker::checkEndPath(CheckerContext &Ctx) const {
+  ProgramStateRef state = Ctx.getState();
+  typedef llvm::ImmutableMap<SymbolRef, StreamState> SymMap;
+  SymMap M = state->get<StreamState>();
+  
+  for (SymMap::iterator I = M.begin(), E = M.end(); I != E; ++I) {
+    StreamState SS = I->second;
+    if (SS.isOpened()) {
+      ExplodedNode *N = Ctx.addTransition(state);
+      if (N) {
+        if (!BT_ResourceLeak)
+          BT_ResourceLeak.reset(new BuiltinBug("Resource Leak", 
+                         "Opened File never closed. Potential Resource leak."));
+        BugReport *R = new BugReport(*BT_ResourceLeak, 
+                                     BT_ResourceLeak->getDescription(), N);
+        Ctx.EmitReport(R);
+      }
+    }
+  }
+}
+
+void StreamChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const {
+  const Expr *RetE = S->getRetValue();
+  if (!RetE)
+    return;
+  
+  ProgramStateRef state = C.getState();
+  SymbolRef Sym = state->getSVal(RetE, C.getLocationContext()).getAsSymbol();
+  
+  if (!Sym)
+    return;
+  
+  const StreamState *SS = state->get<StreamState>(Sym);
+  if(!SS)
+    return;
+
+  if (SS->isOpened())
+    state = state->set<StreamState>(Sym, StreamState::getEscaped(S));
+
+  C.addTransition(state);
+}
+
+void ento::registerStreamChecker(CheckerManager &mgr) {
+  mgr.registerChecker<StreamChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp
new file mode 100644
index 0000000..1133682
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp
@@ -0,0 +1,62 @@
+//== TaintTesterChecker.cpp ----------------------------------- -*- C++ -*--=//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This checker can be used for testing how taint data is propagated.
+//
+//===----------------------------------------------------------------------===//
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class TaintTesterChecker : public Checker< check::PostStmt<Expr> > {
+
+  mutable OwningPtr<BugType> BT;
+  void initBugType() const;
+
+  /// Given a pointer argument, get the symbol of the value it contains
+  /// (points to).
+  SymbolRef getPointedToSymbol(CheckerContext &C,
+                               const Expr* Arg,
+                               bool IssueWarning = true) const;
+
+public:
+  void checkPostStmt(const Expr *E, CheckerContext &C) const;
+};
+}
+
+inline void TaintTesterChecker::initBugType() const {
+  if (!BT)
+    BT.reset(new BugType("Tainted data", "General"));
+}
+
+void TaintTesterChecker::checkPostStmt(const Expr *E,
+                                       CheckerContext &C) const {
+  ProgramStateRef State = C.getState();
+  if (!State)
+    return;
+
+  if (State->isTainted(E, C.getLocationContext())) {
+    if (ExplodedNode *N = C.addTransition()) {
+      initBugType();
+      BugReport *report = new BugReport(*BT, "tainted",N);
+      report->addRange(E->getSourceRange());
+      C.EmitReport(report);
+    }
+  }
+}
+
+void ento::registerTaintTesterChecker(CheckerManager &mgr) {
+  mgr.registerChecker<TaintTesterChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
new file mode 100644
index 0000000..a30f6d5
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
@@ -0,0 +1,112 @@
+//=== UndefBranchChecker.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 UndefBranchChecker, which checks for undefined branch
+// condition.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class UndefBranchChecker : public Checker<check::BranchCondition> {
+  mutable OwningPtr<BuiltinBug> BT;
+
+  struct FindUndefExpr {
+    ProgramStateRef St;
+    const LocationContext *LCtx;
+
+    FindUndefExpr(ProgramStateRef S, const LocationContext *L) 
+      : St(S), LCtx(L) {}
+
+    const Expr *FindExpr(const Expr *Ex) {
+      if (!MatchesCriteria(Ex))
+        return 0;
+
+      for (Stmt::const_child_iterator I = Ex->child_begin(), 
+                                      E = Ex->child_end();I!=E;++I)
+        if (const Expr *ExI = dyn_cast_or_null<Expr>(*I)) {
+          const Expr *E2 = FindExpr(ExI);
+          if (E2) return E2;
+        }
+
+      return Ex;
+    }
+
+    bool MatchesCriteria(const Expr *Ex) { 
+      return St->getSVal(Ex, LCtx).isUndef();
+    }
+  };
+
+public:
+  void checkBranchCondition(const Stmt *Condition, CheckerContext &Ctx) const;
+};
+
+}
+
+void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
+                                              CheckerContext &Ctx) const {
+  SVal X = Ctx.getState()->getSVal(Condition, Ctx.getLocationContext());
+  if (X.isUndef()) {
+    // Generate a sink node, which implicitly marks both outgoing branches as
+    // infeasible.
+    ExplodedNode *N = Ctx.generateSink();
+    if (N) {
+      if (!BT)
+        BT.reset(
+               new BuiltinBug("Branch condition evaluates to a garbage value"));
+
+      // What's going on here: we want to highlight the subexpression of the
+      // condition that is the most likely source of the "uninitialized
+      // branch condition."  We do a recursive walk of the condition's
+      // subexpressions and roughly look for the most nested subexpression
+      // that binds to Undefined.  We then highlight that expression's range.
+
+      // Get the predecessor node and check if is a PostStmt with the Stmt
+      // being the terminator condition.  We want to inspect the state
+      // of that node instead because it will contain main information about
+      // the subexpressions.
+
+      // Note: any predecessor will do.  They should have identical state,
+      // since all the BlockEdge did was act as an error sink since the value
+      // had to already be undefined.
+      assert (!N->pred_empty());
+      const Expr *Ex = cast<Expr>(Condition);
+      ExplodedNode *PrevN = *N->pred_begin();
+      ProgramPoint P = PrevN->getLocation();
+      ProgramStateRef St = N->getState();
+
+      if (PostStmt *PS = dyn_cast<PostStmt>(&P))
+        if (PS->getStmt() == Ex)
+          St = PrevN->getState();
+
+      FindUndefExpr FindIt(St, Ctx.getLocationContext());
+      Ex = FindIt.FindExpr(Ex);
+
+      // Emit the bug report.
+      BugReport *R = new BugReport(*BT, BT->getDescription(), N);
+      R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Ex, R));
+      R->addRange(Ex->getSourceRange());
+
+      Ctx.EmitReport(R);
+    }
+  }
+}
+
+void ento::registerUndefBranchChecker(CheckerManager &mgr) {
+  mgr.registerChecker<UndefBranchChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
new file mode 100644
index 0000000..d57767e
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
@@ -0,0 +1,105 @@
+// UndefCapturedBlockVarChecker.cpp - Uninitialized captured vars -*- C++ -*-=//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This checker detects blocks that capture uninitialized values.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class UndefCapturedBlockVarChecker
+  : public Checker< check::PostStmt<BlockExpr> > {
+ mutable OwningPtr<BugType> BT;
+
+public:
+  void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
+};
+} // end anonymous namespace
+
+static const DeclRefExpr *FindBlockDeclRefExpr(const Stmt *S,
+                                               const VarDecl *VD) {
+  if (const DeclRefExpr *BR = dyn_cast<DeclRefExpr>(S))
+    if (BR->getDecl() == VD)
+      return BR;
+
+  for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
+       I!=E; ++I)
+    if (const Stmt *child = *I) {
+      const DeclRefExpr *BR = FindBlockDeclRefExpr(child, VD);
+      if (BR)
+        return BR;
+    }
+
+  return NULL;
+}
+
+void
+UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE,
+                                            CheckerContext &C) const {
+  if (!BE->getBlockDecl()->hasCaptures())
+    return;
+
+  ProgramStateRef state = C.getState();
+  const BlockDataRegion *R =
+    cast<BlockDataRegion>(state->getSVal(BE,
+                                         C.getLocationContext()).getAsRegion());
+
+  BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
+                                            E = R->referenced_vars_end();
+
+  for (; I != E; ++I) {
+    // This VarRegion is the region associated with the block; we need
+    // the one associated with the encompassing context.
+    const VarRegion *VR = *I;
+    const VarDecl *VD = VR->getDecl();
+
+    if (VD->getAttr<BlocksAttr>() || !VD->hasLocalStorage())
+      continue;
+
+    // Get the VarRegion associated with VD in the local stack frame.
+    const LocationContext *LC = C.getLocationContext();
+    VR = C.getSValBuilder().getRegionManager().getVarRegion(VD, LC);
+    SVal VRVal = state->getSVal(VR);
+
+    if (VRVal.isUndef())
+      if (ExplodedNode *N = C.generateSink()) {
+        if (!BT)
+          BT.reset(new BuiltinBug("uninitialized variable captured by block"));
+
+        // Generate a bug report.
+        SmallString<128> buf;
+        llvm::raw_svector_ostream os(buf);
+
+        os << "Variable '" << VD->getName() 
+           << "' is uninitialized when captured by block";
+
+        BugReport *R = new BugReport(*BT, os.str(), N);
+        if (const Expr *Ex = FindBlockDeclRefExpr(BE->getBody(), VD))
+          R->addRange(Ex->getSourceRange());
+        R->addVisitor(new FindLastStoreBRVisitor(VRVal, VR));
+        // need location of block
+        C.EmitReport(R);
+      }
+  }
+}
+
+void ento::registerUndefCapturedBlockVarChecker(CheckerManager &mgr) {
+  mgr.registerChecker<UndefCapturedBlockVarChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
new file mode 100644
index 0000000..c3c9ed7
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
@@ -0,0 +1,91 @@
+//=== UndefResultChecker.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines UndefResultChecker, a builtin check in ExprEngine that 
+// performs checks for undefined results of non-assignment binary operators.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class UndefResultChecker 
+  : public Checker< check::PostStmt<BinaryOperator> > {
+
+  mutable OwningPtr<BugType> BT;
+  
+public:
+  void checkPostStmt(const BinaryOperator *B, CheckerContext &C) const;
+};
+} // end anonymous namespace
+
+void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
+                                       CheckerContext &C) const {
+  ProgramStateRef state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
+  if (state->getSVal(B, LCtx).isUndef()) {
+    // Generate an error node.
+    ExplodedNode *N = C.generateSink();
+    if (!N)
+      return;
+    
+    if (!BT)
+      BT.reset(new BuiltinBug("Result of operation is garbage or undefined"));
+
+    SmallString<256> sbuf;
+    llvm::raw_svector_ostream OS(sbuf);
+    const Expr *Ex = NULL;
+    bool isLeft = true;
+    
+    if (state->getSVal(B->getLHS(), LCtx).isUndef()) {
+      Ex = B->getLHS()->IgnoreParenCasts();
+      isLeft = true;
+    }
+    else if (state->getSVal(B->getRHS(), LCtx).isUndef()) {
+      Ex = B->getRHS()->IgnoreParenCasts();
+      isLeft = false;
+    }
+    
+    if (Ex) {
+      OS << "The " << (isLeft ? "left" : "right")
+         << " operand of '"
+         << BinaryOperator::getOpcodeStr(B->getOpcode())
+         << "' is a garbage value";
+    }          
+    else {
+      // Neither operand was undefined, but the result is undefined.
+      OS << "The result of the '"
+         << BinaryOperator::getOpcodeStr(B->getOpcode())
+         << "' expression is undefined";
+    }
+    BugReport *report = new BugReport(*BT, OS.str(), N);
+    if (Ex) {
+      report->addRange(Ex->getSourceRange());
+      report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Ex,
+                                                                      report));
+    }
+    else
+      report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, B,
+                                                                      report));
+    C.EmitReport(report);
+  }
+}
+
+void ento::registerUndefResultChecker(CheckerManager &mgr) {
+  mgr.registerChecker<UndefResultChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
new file mode 100644
index 0000000..0297c4e
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
@@ -0,0 +1,55 @@
+//===--- UndefinedArraySubscriptChecker.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 UndefinedArraySubscriptChecker, a builtin check in ExprEngine
+// that performs checks for undefined array subscripts.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class UndefinedArraySubscriptChecker
+  : public Checker< check::PreStmt<ArraySubscriptExpr> > {
+  mutable OwningPtr<BugType> BT;
+
+public:
+  void checkPreStmt(const ArraySubscriptExpr *A, CheckerContext &C) const;
+};
+} // end anonymous namespace
+
+void 
+UndefinedArraySubscriptChecker::checkPreStmt(const ArraySubscriptExpr *A,
+                                             CheckerContext &C) const {
+  if (C.getState()->getSVal(A->getIdx(), C.getLocationContext()).isUndef()) {
+    if (ExplodedNode *N = C.generateSink()) {
+      if (!BT)
+        BT.reset(new BuiltinBug("Array subscript is undefined"));
+
+      // Generate a report for this bug.
+      BugReport *R = new BugReport(*BT, BT->getName(), N);
+      R->addRange(A->getIdx()->getSourceRange());
+      R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
+                                                                 A->getIdx(),
+                                                                 R));
+      C.EmitReport(R);
+    }
+  }
+}
+
+void ento::registerUndefinedArraySubscriptChecker(CheckerManager &mgr) {
+  mgr.registerChecker<UndefinedArraySubscriptChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
new file mode 100644
index 0000000..78f7fa6
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
@@ -0,0 +1,88 @@
+//===--- 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 UndefinedAssignmentChecker, a builtin check in ExprEngine that
+// checks for assigning undefined values.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class UndefinedAssignmentChecker
+  : public Checker<check::Bind> {
+  mutable OwningPtr<BugType> BT;
+
+public:
+  void checkBind(SVal location, SVal val, const Stmt *S,
+                 CheckerContext &C) const;
+};
+}
+
+void UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
+                                           const Stmt *StoreE,
+                                           CheckerContext &C) const {
+  if (!val.isUndef())
+    return;
+
+  ExplodedNode *N = C.generateSink();
+
+  if (!N)
+    return;
+
+  const char *str = "Assigned value is garbage or undefined";
+
+  if (!BT)
+    BT.reset(new BuiltinBug(str));
+
+  // Generate a report for this bug.
+  const Expr *ex = 0;
+
+  while (StoreE) {
+    if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) {
+      if (B->isCompoundAssignmentOp()) {
+        ProgramStateRef state = C.getState();
+        if (state->getSVal(B->getLHS(), C.getLocationContext()).isUndef()) {
+          str = "The left expression of the compound assignment is an "
+                "uninitialized value. The computed value will also be garbage";
+          ex = B->getLHS();
+          break;
+        }
+      }
+
+      ex = B->getRHS();
+      break;
+    }
+
+    if (const DeclStmt *DS = dyn_cast<DeclStmt>(StoreE)) {
+      const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
+      ex = VD->getInit();
+    }
+
+    break;
+  }
+
+  BugReport *R = new BugReport(*BT, str, N);
+  if (ex) {
+    R->addRange(ex->getSourceRange());
+    R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, ex, R));
+  }
+  C.EmitReport(R);
+}
+
+void ento::registerUndefinedAssignmentChecker(CheckerManager &mgr) {
+  mgr.registerChecker<UndefinedAssignmentChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
new file mode 100644
index 0000000..60e665f
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
@@ -0,0 +1,353 @@
+//= UnixAPIChecker.h - Checks preconditions for various Unix APIs --*- C++ -*-//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines UnixAPIChecker, which is an assortment of checks on calls
+// to various, widely used UNIX/Posix functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include <fcntl.h>
+
+using namespace clang;
+using namespace ento;
+using llvm::Optional;
+
+namespace {
+class UnixAPIChecker : public Checker< check::PreStmt<CallExpr> > {
+  mutable OwningPtr<BugType> BT_open, BT_pthreadOnce, BT_mallocZero;
+  mutable Optional<uint64_t> Val_O_CREAT;
+
+public:
+  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
+
+  void CheckOpen(CheckerContext &C, const CallExpr *CE) const;
+  void CheckPthreadOnce(CheckerContext &C, const CallExpr *CE) const;
+  void CheckCallocZero(CheckerContext &C, const CallExpr *CE) const;
+  void CheckMallocZero(CheckerContext &C, const CallExpr *CE) const;
+  void CheckReallocZero(CheckerContext &C, const CallExpr *CE) const;
+  void CheckAllocaZero(CheckerContext &C, const CallExpr *CE) const;
+  void CheckVallocZero(CheckerContext &C, const CallExpr *CE) const;
+
+  typedef void (UnixAPIChecker::*SubChecker)(CheckerContext &,
+                                             const CallExpr *) const;
+private:
+  bool ReportZeroByteAllocation(CheckerContext &C,
+                                ProgramStateRef falseState,
+                                const Expr *arg,
+                                const char *fn_name) const;
+  void BasicAllocationCheck(CheckerContext &C,
+                            const CallExpr *CE,
+                            const unsigned numArgs,
+                            const unsigned sizeArg,
+                            const char *fn) const;
+};
+} //end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Utility functions.
+//===----------------------------------------------------------------------===//
+
+static inline void LazyInitialize(OwningPtr<BugType> &BT,
+                                  const char *name) {
+  if (BT)
+    return;
+  BT.reset(new BugType(name, categories::UnixAPI));
+}
+
+//===----------------------------------------------------------------------===//
+// "open" (man 2 open)
+//===----------------------------------------------------------------------===//
+
+void UnixAPIChecker::CheckOpen(CheckerContext &C, const CallExpr *CE) const {
+  // The definition of O_CREAT is platform specific.  We need a better way
+  // of querying this information from the checking environment.
+  if (!Val_O_CREAT.hasValue()) {
+    if (C.getASTContext().getTargetInfo().getTriple().getVendor() 
+                                                      == llvm::Triple::Apple)
+      Val_O_CREAT = 0x0200;
+    else {
+      // FIXME: We need a more general way of getting the O_CREAT value.
+      // We could possibly grovel through the preprocessor state, but
+      // that would require passing the Preprocessor object to the ExprEngine.
+      return;
+    }
+  }
+
+  // Look at the 'oflags' argument for the O_CREAT flag.
+  ProgramStateRef state = C.getState();
+
+  if (CE->getNumArgs() < 2) {
+    // The frontend should issue a warning for this case, so this is a sanity
+    // check.
+    return;
+  }
+
+  // Now check if oflags has O_CREAT set.
+  const Expr *oflagsEx = CE->getArg(1);
+  const SVal V = state->getSVal(oflagsEx, C.getLocationContext());
+  if (!isa<NonLoc>(V)) {
+    // The case where 'V' can be a location can only be due to a bad header,
+    // so in this case bail out.
+    return;
+  }
+  NonLoc oflags = cast<NonLoc>(V);
+  NonLoc ocreateFlag =
+    cast<NonLoc>(C.getSValBuilder().makeIntVal(Val_O_CREAT.getValue(),
+                                                oflagsEx->getType()));
+  SVal maskedFlagsUC = C.getSValBuilder().evalBinOpNN(state, BO_And,
+                                                      oflags, ocreateFlag,
+                                                      oflagsEx->getType());
+  if (maskedFlagsUC.isUnknownOrUndef())
+    return;
+  DefinedSVal maskedFlags = cast<DefinedSVal>(maskedFlagsUC);
+
+  // Check if maskedFlags is non-zero.
+  ProgramStateRef trueState, falseState;
+  llvm::tie(trueState, falseState) = state->assume(maskedFlags);
+
+  // Only emit an error if the value of 'maskedFlags' is properly
+  // constrained;
+  if (!(trueState && !falseState))
+    return;
+
+  if (CE->getNumArgs() < 3) {
+    ExplodedNode *N = C.generateSink(trueState);
+    if (!N)
+      return;
+
+    LazyInitialize(BT_open, "Improper use of 'open'");
+
+    BugReport *report =
+      new BugReport(*BT_open,
+                            "Call to 'open' requires a third argument when "
+                            "the 'O_CREAT' flag is set", N);
+    report->addRange(oflagsEx->getSourceRange());
+    C.EmitReport(report);
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// pthread_once
+//===----------------------------------------------------------------------===//
+
+void UnixAPIChecker::CheckPthreadOnce(CheckerContext &C,
+                                      const CallExpr *CE) const {
+
+  // This is similar to 'CheckDispatchOnce' in the MacOSXAPIChecker.
+  // They can possibly be refactored.
+
+  if (CE->getNumArgs() < 1)
+    return;
+
+  // Check if the first argument is stack allocated.  If so, issue a warning
+  // because that's likely to be bad news.
+  ProgramStateRef state = C.getState();
+  const MemRegion *R =
+    state->getSVal(CE->getArg(0), C.getLocationContext()).getAsRegion();
+  if (!R || !isa<StackSpaceRegion>(R->getMemorySpace()))
+    return;
+
+  ExplodedNode *N = C.generateSink(state);
+  if (!N)
+    return;
+
+  SmallString<256> S;
+  llvm::raw_svector_ostream os(S);
+  os << "Call to 'pthread_once' uses";
+  if (const VarRegion *VR = dyn_cast<VarRegion>(R))
+    os << " the local variable '" << VR->getDecl()->getName() << '\'';
+  else
+    os << " stack allocated memory";
+  os << " for the \"control\" value.  Using such transient memory for "
+  "the control value is potentially dangerous.";
+  if (isa<VarRegion>(R) && isa<StackLocalsSpaceRegion>(R->getMemorySpace()))
+    os << "  Perhaps you intended to declare the variable as 'static'?";
+
+  LazyInitialize(BT_pthreadOnce, "Improper use of 'pthread_once'");
+
+  BugReport *report = new BugReport(*BT_pthreadOnce, os.str(), N);
+  report->addRange(CE->getArg(0)->getSourceRange());
+  C.EmitReport(report);
+}
+
+//===----------------------------------------------------------------------===//
+// "calloc", "malloc", "realloc", "alloca" and "valloc" with allocation size 0
+//===----------------------------------------------------------------------===//
+// FIXME: Eventually these should be rolled into the MallocChecker, but right now
+// they're more basic and valuable for widespread use.
+
+// Returns true if we try to do a zero byte allocation, false otherwise.
+// Fills in trueState and falseState.
+static bool IsZeroByteAllocation(ProgramStateRef state,
+                                const SVal argVal,
+                                ProgramStateRef *trueState,
+                                ProgramStateRef *falseState) {
+  llvm::tie(*trueState, *falseState) =
+    state->assume(cast<DefinedSVal>(argVal));
+  
+  return (*falseState && !*trueState);
+}
+
+// Generates an error report, indicating that the function whose name is given
+// will perform a zero byte allocation.
+// Returns false if an error occured, true otherwise.
+bool UnixAPIChecker::ReportZeroByteAllocation(CheckerContext &C,
+                                              ProgramStateRef falseState,
+                                              const Expr *arg,
+                                              const char *fn_name) const {
+  ExplodedNode *N = C.generateSink(falseState);
+  if (!N)
+    return false;
+
+  LazyInitialize(BT_mallocZero,
+    "Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)");
+
+  SmallString<256> S;
+  llvm::raw_svector_ostream os(S);    
+  os << "Call to '" << fn_name << "' has an allocation size of 0 bytes";
+  BugReport *report = new BugReport(*BT_mallocZero, os.str(), N);
+
+  report->addRange(arg->getSourceRange());
+  report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, arg,
+                                                                  report));
+  C.EmitReport(report);
+
+  return true;
+}
+
+// Does a basic check for 0-sized allocations suitable for most of the below
+// functions (modulo "calloc")
+void UnixAPIChecker::BasicAllocationCheck(CheckerContext &C,
+                                          const CallExpr *CE,
+                                          const unsigned numArgs,
+                                          const unsigned sizeArg,
+                                          const char *fn) const {
+  // Sanity check for the correct number of arguments
+  if (CE->getNumArgs() != numArgs)
+    return;
+
+  // Check if the allocation size is 0.
+  ProgramStateRef state = C.getState();
+  ProgramStateRef trueState = NULL, falseState = NULL;
+  const Expr *arg = CE->getArg(sizeArg);
+  SVal argVal = state->getSVal(arg, C.getLocationContext());
+
+  if (argVal.isUnknownOrUndef())
+    return;
+
+  // Is the value perfectly constrained to zero?
+  if (IsZeroByteAllocation(state, argVal, &trueState, &falseState)) {
+    (void) ReportZeroByteAllocation(C, falseState, arg, fn); 
+    return;
+  }
+  // Assume the the value is non-zero going forward.
+  assert(trueState);
+  if (trueState != state)
+    C.addTransition(trueState);                           
+}
+
+void UnixAPIChecker::CheckCallocZero(CheckerContext &C,
+                                     const CallExpr *CE) const {
+  unsigned int nArgs = CE->getNumArgs();
+  if (nArgs != 2)
+    return;
+
+  ProgramStateRef state = C.getState();
+  ProgramStateRef trueState = NULL, falseState = NULL;
+
+  unsigned int i;
+  for (i = 0; i < nArgs; i++) {
+    const Expr *arg = CE->getArg(i);
+    SVal argVal = state->getSVal(arg, C.getLocationContext());
+    if (argVal.isUnknownOrUndef()) {
+      if (i == 0)
+        continue;
+      else
+        return;
+    }
+
+    if (IsZeroByteAllocation(state, argVal, &trueState, &falseState)) {
+      if (ReportZeroByteAllocation(C, falseState, arg, "calloc"))
+        return;
+      else if (i == 0)
+        continue;
+      else
+        return;
+    }
+  }
+
+  // Assume the the value is non-zero going forward.
+  assert(trueState);
+  if (trueState != state)
+    C.addTransition(trueState);
+}
+
+void UnixAPIChecker::CheckMallocZero(CheckerContext &C,
+                                     const CallExpr *CE) const {
+  BasicAllocationCheck(C, CE, 1, 0, "malloc");
+}
+
+void UnixAPIChecker::CheckReallocZero(CheckerContext &C,
+                                      const CallExpr *CE) const {
+  BasicAllocationCheck(C, CE, 2, 1, "realloc");
+}
+
+void UnixAPIChecker::CheckAllocaZero(CheckerContext &C,
+                                     const CallExpr *CE) const {
+  BasicAllocationCheck(C, CE, 1, 0, "alloca");
+}
+
+void UnixAPIChecker::CheckVallocZero(CheckerContext &C,
+                                     const CallExpr *CE) const {
+  BasicAllocationCheck(C, CE, 1, 0, "valloc");
+}
+
+
+//===----------------------------------------------------------------------===//
+// Central dispatch function.
+//===----------------------------------------------------------------------===//
+
+void UnixAPIChecker::checkPreStmt(const CallExpr *CE,
+                                  CheckerContext &C) const {
+  StringRef FName = C.getCalleeName(CE);
+  if (FName.empty())
+    return;
+
+  SubChecker SC =
+    llvm::StringSwitch<SubChecker>(FName)
+      .Case("open", &UnixAPIChecker::CheckOpen)
+      .Case("pthread_once", &UnixAPIChecker::CheckPthreadOnce)
+      .Case("calloc", &UnixAPIChecker::CheckCallocZero)
+      .Case("malloc", &UnixAPIChecker::CheckMallocZero)
+      .Case("realloc", &UnixAPIChecker::CheckReallocZero)
+      .Cases("alloca", "__builtin_alloca", &UnixAPIChecker::CheckAllocaZero)
+      .Case("valloc", &UnixAPIChecker::CheckVallocZero)
+      .Default(NULL);
+
+  if (SC)
+    (this->*SC)(C, CE);
+}
+
+//===----------------------------------------------------------------------===//
+// Registration.
+//===----------------------------------------------------------------------===//
+
+void ento::registerUnixAPIChecker(CheckerManager &mgr) {
+  mgr.registerChecker<UnixAPIChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
new file mode 100644
index 0000000..5a13ed0
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
@@ -0,0 +1,247 @@
+//==- UnreachableCodeChecker.cpp - Generalized dead code checker -*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This file implements a generalized unreachable code checker using a
+// path-sensitive analysis. We mark any path visited, and then walk the CFG as a
+// post-analysis to determine what was never visited.
+//
+// A similar flow-sensitive only check exists in Analysis/ReachableCode.cpp
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/SmallSet.h"
+
+// The number of CFGBlock pointers we want to reserve memory for. This is used
+// once for each function we analyze.
+#define DEFAULT_CFGBLOCKS 256
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class UnreachableCodeChecker : public Checker<check::EndAnalysis> {
+public:
+  void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,
+                        ExprEngine &Eng) const;
+private:
+  typedef llvm::SmallSet<unsigned, DEFAULT_CFGBLOCKS> CFGBlocksSet;
+
+  static inline const Stmt *getUnreachableStmt(const CFGBlock *CB);
+  static void FindUnreachableEntryPoints(const CFGBlock *CB,
+                                         CFGBlocksSet &reachable,
+                                         CFGBlocksSet &visited);
+  static bool isInvalidPath(const CFGBlock *CB, const ParentMap &PM);
+  static inline bool isEmptyCFGBlock(const CFGBlock *CB);
+};
+}
+
+void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G,
+                                              BugReporter &B,
+                                              ExprEngine &Eng) const {
+  CFGBlocksSet reachable, visited;
+  
+  if (Eng.hasWorkRemaining())
+    return;
+
+  const Decl *D = 0;
+  CFG *C = 0;
+  ParentMap *PM = 0;
+  const LocationContext *LC = 0;
+  // Iterate over ExplodedGraph
+  for (ExplodedGraph::node_iterator I = G.nodes_begin(), E = G.nodes_end();
+      I != E; ++I) {
+    const ProgramPoint &P = I->getLocation();
+    LC = P.getLocationContext();
+
+    if (!D)
+      D = LC->getAnalysisDeclContext()->getDecl();
+    // Save the CFG if we don't have it already
+    if (!C)
+      C = LC->getAnalysisDeclContext()->getUnoptimizedCFG();
+    if (!PM)
+      PM = &LC->getParentMap();
+
+    if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) {
+      const CFGBlock *CB = BE->getBlock();
+      reachable.insert(CB->getBlockID());
+    }
+  }
+
+  // Bail out if we didn't get the CFG or the ParentMap.
+  if (!D || !C || !PM)
+    return;
+  
+  // Don't do anything for template instantiations.  Proving that code
+  // in a template instantiation is unreachable means proving that it is
+  // unreachable in all instantiations.
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+    if (FD->isTemplateInstantiation())
+      return;
+
+  // Find CFGBlocks that were not covered by any node
+  for (CFG::const_iterator I = C->begin(), E = C->end(); I != E; ++I) {
+    const CFGBlock *CB = *I;
+    // Check if the block is unreachable
+    if (reachable.count(CB->getBlockID()))
+      continue;
+
+    // Check if the block is empty (an artificial block)
+    if (isEmptyCFGBlock(CB))
+      continue;
+
+    // Find the entry points for this block
+    if (!visited.count(CB->getBlockID()))
+      FindUnreachableEntryPoints(CB, reachable, visited);
+
+    // This block may have been pruned; check if we still want to report it
+    if (reachable.count(CB->getBlockID()))
+      continue;
+
+    // Check for false positives
+    if (CB->size() > 0 && isInvalidPath(CB, *PM))
+      continue;
+
+    // It is good practice to always have a "default" label in a "switch", even
+    // if we should never get there. It can be used to detect errors, for
+    // instance. Unreachable code directly under a "default" label is therefore
+    // likely to be a false positive.
+    if (const Stmt *label = CB->getLabel())
+      if (label->getStmtClass() == Stmt::DefaultStmtClass)
+        continue;
+
+    // Special case for __builtin_unreachable.
+    // FIXME: This should be extended to include other unreachable markers,
+    // such as llvm_unreachable.
+    if (!CB->empty()) {
+      bool foundUnreachable = false;
+      for (CFGBlock::const_iterator ci = CB->begin(), ce = CB->end();
+           ci != ce; ++ci) {
+        if (const CFGStmt *S = (*ci).getAs<CFGStmt>())
+          if (const CallExpr *CE = dyn_cast<CallExpr>(S->getStmt())) {
+            if (CE->isBuiltinCall() == Builtin::BI__builtin_unreachable) {
+              foundUnreachable = true;
+              break;
+            }
+          }
+      }
+      if (foundUnreachable)
+        continue;
+    }
+
+    // We found a block that wasn't covered - find the statement to report
+    SourceRange SR;
+    PathDiagnosticLocation DL;
+    SourceLocation SL;
+    if (const Stmt *S = getUnreachableStmt(CB)) {
+      SR = S->getSourceRange();
+      DL = PathDiagnosticLocation::createBegin(S, B.getSourceManager(), LC);
+      SL = DL.asLocation();
+      if (SR.isInvalid() || !SL.isValid())
+        continue;
+    }
+    else
+      continue;
+
+    // Check if the SourceLocation is in a system header
+    const SourceManager &SM = B.getSourceManager();
+    if (SM.isInSystemHeader(SL) || SM.isInExternCSystemHeader(SL))
+      continue;
+
+    B.EmitBasicReport(D, "Unreachable code", "Dead code",
+                      "This statement is never executed", DL, SR);
+  }
+}
+
+// Recursively finds the entry point(s) for this dead CFGBlock.
+void UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB,
+                                                        CFGBlocksSet &reachable,
+                                                        CFGBlocksSet &visited) {
+  visited.insert(CB->getBlockID());
+
+  for (CFGBlock::const_pred_iterator I = CB->pred_begin(), E = CB->pred_end();
+      I != E; ++I) {
+    if (!reachable.count((*I)->getBlockID())) {
+      // If we find an unreachable predecessor, mark this block as reachable so
+      // we don't report this block
+      reachable.insert(CB->getBlockID());
+      if (!visited.count((*I)->getBlockID()))
+        // If we haven't previously visited the unreachable predecessor, recurse
+        FindUnreachableEntryPoints(*I, reachable, visited);
+    }
+  }
+}
+
+// Find the Stmt* in a CFGBlock for reporting a warning
+const Stmt *UnreachableCodeChecker::getUnreachableStmt(const CFGBlock *CB) {
+  for (CFGBlock::const_iterator I = CB->begin(), E = CB->end(); I != E; ++I) {
+    if (const CFGStmt *S = I->getAs<CFGStmt>())
+      return S->getStmt();
+  }
+  if (const Stmt *S = CB->getTerminator())
+    return S;
+  else
+    return 0;
+}
+
+// Determines if the path to this CFGBlock contained an element that infers this
+// block is a false positive. We assume that FindUnreachableEntryPoints has
+// already marked only the entry points to any dead code, so we need only to
+// find the condition that led to this block (the predecessor of this block.)
+// There will never be more than one predecessor.
+bool UnreachableCodeChecker::isInvalidPath(const CFGBlock *CB,
+                                           const ParentMap &PM) {
+  // We only expect a predecessor size of 0 or 1. If it is >1, then an external
+  // condition has broken our assumption (for example, a sink being placed by
+  // another check). In these cases, we choose not to report.
+  if (CB->pred_size() > 1)
+    return true;
+
+  // If there are no predecessors, then this block is trivially unreachable
+  if (CB->pred_size() == 0)
+    return false;
+
+  const CFGBlock *pred = *CB->pred_begin();
+
+  // Get the predecessor block's terminator conditon
+  const Stmt *cond = pred->getTerminatorCondition();
+
+  //assert(cond && "CFGBlock's predecessor has a terminator condition");
+  // The previous assertion is invalid in some cases (eg do/while). Leaving
+  // reporting of these situations on at the moment to help triage these cases.
+  if (!cond)
+    return false;
+
+  // Run each of the checks on the conditions
+  if (containsMacro(cond) || containsEnum(cond)
+      || containsStaticLocal(cond) || containsBuiltinOffsetOf(cond)
+      || containsStmt<UnaryExprOrTypeTraitExpr>(cond))
+    return true;
+
+  return false;
+}
+
+// Returns true if the given CFGBlock is empty
+bool UnreachableCodeChecker::isEmptyCFGBlock(const CFGBlock *CB) {
+  return CB->getLabel() == 0       // No labels
+      && CB->size() == 0           // No statements
+      && CB->getTerminator() == 0; // No terminator
+}
+
+void ento::registerUnreachableCodeChecker(CheckerManager &mgr) {
+  mgr.registerChecker<UnreachableCodeChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
new file mode 100644
index 0000000..38c9cc1
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
@@ -0,0 +1,162 @@
+//=== 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 VLASizeChecker, a builtin check in ExprEngine that 
+// performs checks for declaration of VLA of undefined or zero size.
+// In addition, VLASizeChecker is responsible for defining the extent
+// of the MemRegion that represents a VLA.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/AST/CharUnits.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/STLExtras.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class VLASizeChecker : public Checker< check::PreStmt<DeclStmt> > {
+  mutable OwningPtr<BugType> BT;
+  enum VLASize_Kind { VLA_Garbage, VLA_Zero, VLA_Tainted };
+
+  void reportBug(VLASize_Kind Kind,
+                 const Expr *SizeE,
+                 ProgramStateRef State,
+                 CheckerContext &C) const;
+public:
+  void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const;
+};
+} // end anonymous namespace
+
+void VLASizeChecker::reportBug(VLASize_Kind Kind,
+                               const Expr *SizeE,
+                               ProgramStateRef State,
+                               CheckerContext &C) const {
+  // Generate an error node.
+  ExplodedNode *N = C.generateSink(State);
+  if (!N)
+    return;
+
+  if (!BT)
+    BT.reset(new BuiltinBug("Dangerous variable-length array (VLA) declaration"));
+
+  SmallString<256> buf;
+  llvm::raw_svector_ostream os(buf);
+  os << "Declared variable-length array (VLA) ";
+  switch (Kind) {
+  case VLA_Garbage:
+    os << "uses a garbage value as its size";
+    break;
+  case VLA_Zero:
+    os << "has zero size";
+    break;
+  case VLA_Tainted:
+    os << "has tainted size";
+    break;
+  }
+
+  BugReport *report = new BugReport(*BT, os.str(), N);
+  report->addRange(SizeE->getSourceRange());
+  report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, SizeE,
+                                                                  report));
+  C.EmitReport(report);
+  return;
+}
+
+void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
+  if (!DS->isSingleDecl())
+    return;
+  
+  const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
+  if (!VD)
+    return;
+
+  ASTContext &Ctx = C.getASTContext();
+  const VariableArrayType *VLA = Ctx.getAsVariableArrayType(VD->getType());
+  if (!VLA)
+    return;
+
+  // FIXME: Handle multi-dimensional VLAs.
+  const Expr *SE = VLA->getSizeExpr();
+  ProgramStateRef state = C.getState();
+  SVal sizeV = state->getSVal(SE, C.getLocationContext());
+
+  if (sizeV.isUndef()) {
+    reportBug(VLA_Garbage, SE, state, C);
+    return;
+  }
+
+  // See if the size value is known. It can't be undefined because we would have
+  // warned about that already.
+  if (sizeV.isUnknown())
+    return;
+  
+  // Check if the size is tainted.
+  if (state->isTainted(sizeV)) {
+    reportBug(VLA_Tainted, SE, 0, C);
+    return;
+  }
+
+  // Check if the size is zero.
+  DefinedSVal sizeD = cast<DefinedSVal>(sizeV);
+
+  ProgramStateRef stateNotZero, stateZero;
+  llvm::tie(stateNotZero, stateZero) = state->assume(sizeD);
+
+  if (stateZero && !stateNotZero) {
+    reportBug(VLA_Zero, SE, stateZero, C);
+    return;
+  }
+ 
+  // From this point on, assume that the size is not zero.
+  state = stateNotZero;
+
+  // VLASizeChecker is responsible for defining the extent of the array being
+  // declared. We do this by multiplying the array length by the element size,
+  // then matching that with the array region's extent symbol.
+
+  // Convert the array length to size_t.
+  SValBuilder &svalBuilder = C.getSValBuilder();
+  QualType SizeTy = Ctx.getSizeType();
+  NonLoc ArrayLength = cast<NonLoc>(svalBuilder.evalCast(sizeD, SizeTy, 
+                                                         SE->getType()));
+
+  // Get the element size.
+  CharUnits EleSize = Ctx.getTypeSizeInChars(VLA->getElementType());
+  SVal EleSizeVal = svalBuilder.makeIntVal(EleSize.getQuantity(), SizeTy);
+
+  // Multiply the array length by the element size.
+  SVal ArraySizeVal = svalBuilder.evalBinOpNN(state, BO_Mul, ArrayLength,
+                                              cast<NonLoc>(EleSizeVal), SizeTy);
+
+  // Finally, assume that the array's extent matches the given size.
+  const LocationContext *LC = C.getLocationContext();
+  DefinedOrUnknownSVal Extent =
+    state->getRegion(VD, LC)->getExtent(svalBuilder);
+  DefinedOrUnknownSVal ArraySize = cast<DefinedOrUnknownSVal>(ArraySizeVal);
+  DefinedOrUnknownSVal sizeIsKnown =
+    svalBuilder.evalEQ(state, Extent, ArraySize);
+  state = state->assume(sizeIsKnown, true);
+
+  // Assume should not fail at this point.
+  assert(state);
+
+  // Remember our assumptions!
+  C.addTransition(state);
+}
+
+void ento::registerVLASizeChecker(CheckerManager &mgr) {
+  mgr.registerChecker<VLASizeChecker>();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
new file mode 100644
index 0000000..f7c7c0c
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
@@ -0,0 +1,241 @@
+//=======- VirtualCallChecker.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 checker that checks virtual function calls during 
+//  construction or destruction of C++ objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/StmtVisitor.h"
+#include "llvm/Support/SaveAndRestore.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class WalkAST : public StmtVisitor<WalkAST> {
+  BugReporter &BR;
+  AnalysisDeclContext *AC;
+
+  typedef const CallExpr * WorkListUnit;
+  typedef SmallVector<WorkListUnit, 20> DFSWorkList;
+
+  /// A vector representing the worklist which has a chain of CallExprs.
+  DFSWorkList WList;
+  
+  // PreVisited : A CallExpr to this FunctionDecl is in the worklist, but the
+  // body has not been visited yet.
+  // PostVisited : A CallExpr to this FunctionDecl is in the worklist, and the
+  // body has been visited.
+  enum Kind { NotVisited,
+              PreVisited,  /**< A CallExpr to this FunctionDecl is in the 
+                                worklist, but the body has not yet been
+                                visited. */
+              PostVisited  /**< A CallExpr to this FunctionDecl is in the
+                                worklist, and the body has been visited. */
+  } K;
+
+  /// A DenseMap that records visited states of FunctionDecls.
+  llvm::DenseMap<const FunctionDecl *, Kind> VisitedFunctions;
+
+  /// The CallExpr whose body is currently being visited.  This is used for
+  /// generating bug reports.  This is null while visiting the body of a
+  /// constructor or destructor.
+  const CallExpr *visitingCallExpr;
+  
+public:
+  WalkAST(BugReporter &br, AnalysisDeclContext *ac)
+    : BR(br),
+      AC(ac),
+      visitingCallExpr(0) {}
+  
+  bool hasWork() const { return !WList.empty(); }
+
+  /// This method adds a CallExpr to the worklist and marks the callee as
+  /// being PreVisited.
+  void Enqueue(WorkListUnit WLUnit) {
+    const FunctionDecl *FD = WLUnit->getDirectCallee();
+    if (!FD || !FD->getBody())
+      return;    
+    Kind &K = VisitedFunctions[FD];
+    if (K != NotVisited)
+      return;
+    K = PreVisited;
+    WList.push_back(WLUnit);
+  }
+
+  /// This method returns an item from the worklist without removing it.
+  WorkListUnit Dequeue() {
+    assert(!WList.empty());
+    return WList.back();    
+  }
+  
+  void Execute() {
+    while (hasWork()) {
+      WorkListUnit WLUnit = Dequeue();
+      const FunctionDecl *FD = WLUnit->getDirectCallee();
+      assert(FD && FD->getBody());
+
+      if (VisitedFunctions[FD] == PreVisited) {
+        // If the callee is PreVisited, walk its body.
+        // Visit the body.
+        SaveAndRestore<const CallExpr *> SaveCall(visitingCallExpr, WLUnit);
+        Visit(FD->getBody());
+        
+        // Mark the function as being PostVisited to indicate we have
+        // scanned the body.
+        VisitedFunctions[FD] = PostVisited;
+        continue;
+      }
+
+      // Otherwise, the callee is PostVisited.
+      // Remove it from the worklist.
+      assert(VisitedFunctions[FD] == PostVisited);
+      WList.pop_back();
+    }
+  }
+
+  // Stmt visitor methods.
+  void VisitCallExpr(CallExpr *CE);
+  void VisitCXXMemberCallExpr(CallExpr *CE);
+  void VisitStmt(Stmt *S) { VisitChildren(S); }
+  void VisitChildren(Stmt *S);
+  
+  void ReportVirtualCall(const CallExpr *CE, bool isPure);
+
+};
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// AST walking.
+//===----------------------------------------------------------------------===//
+
+void WalkAST::VisitChildren(Stmt *S) {
+  for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
+    if (Stmt *child = *I)
+      Visit(child);
+}
+
+void WalkAST::VisitCallExpr(CallExpr *CE) {
+  VisitChildren(CE);
+  Enqueue(CE);
+}
+
+void WalkAST::VisitCXXMemberCallExpr(CallExpr *CE) {
+  VisitChildren(CE);
+  bool callIsNonVirtual = false;
+  
+  // Several situations to elide for checking.
+  if (MemberExpr *CME = dyn_cast<MemberExpr>(CE->getCallee())) {
+    // If the member access is fully qualified (i.e., X::F), then treat
+    // this as a non-virtual call and do not warn.
+    if (CME->getQualifier())
+      callIsNonVirtual = true;
+
+    // Elide analyzing the call entirely if the base pointer is not 'this'.
+    if (Expr *base = CME->getBase()->IgnoreImpCasts())
+      if (!isa<CXXThisExpr>(base))
+        return;
+  }
+
+  // Get the callee.
+  const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CE->getDirectCallee());
+  if (MD && MD->isVirtual() && !callIsNonVirtual)
+    ReportVirtualCall(CE, MD->isPure());
+
+  Enqueue(CE);
+}
+
+void WalkAST::ReportVirtualCall(const CallExpr *CE, bool isPure) {
+  SmallString<100> buf;
+  llvm::raw_svector_ostream os(buf);
+  
+  os << "Call Path : ";
+  // Name of current visiting CallExpr.
+  os << *CE->getDirectCallee();
+
+  // Name of the CallExpr whose body is current walking.
+  if (visitingCallExpr)
+    os << " <-- " << *visitingCallExpr->getDirectCallee();
+  // Names of FunctionDecls in worklist with state PostVisited.
+  for (SmallVectorImpl<const CallExpr *>::iterator I = WList.end(),
+         E = WList.begin(); I != E; --I) {
+    const FunctionDecl *FD = (*(I-1))->getDirectCallee();
+    assert(FD);
+    if (VisitedFunctions[FD] == PostVisited)
+      os << " <-- " << *FD;
+  }
+
+  PathDiagnosticLocation CELoc =
+    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
+  SourceRange R = CE->getCallee()->getSourceRange();
+  
+  if (isPure) {
+    os << "\n" <<  "Call pure virtual functions during construction or "
+       << "destruction may leads undefined behaviour";
+    BR.EmitBasicReport(AC->getDecl(),
+                       "Call pure virtual function during construction or "
+                       "Destruction",
+                       "Cplusplus",
+                       os.str(), CELoc, &R, 1);
+    return;
+  }
+  else {
+    os << "\n" << "Call virtual functions during construction or "
+       << "destruction will never go to a more derived class";
+    BR.EmitBasicReport(AC->getDecl(),
+                       "Call virtual function during construction or "
+                       "Destruction",
+                       "Cplusplus",
+                       os.str(), CELoc, &R, 1);
+    return;
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// VirtualCallChecker
+//===----------------------------------------------------------------------===//
+
+namespace {
+class VirtualCallChecker : public Checker<check::ASTDecl<CXXRecordDecl> > {
+public:
+  void checkASTDecl(const CXXRecordDecl *RD, AnalysisManager& mgr,
+                    BugReporter &BR) const {
+    WalkAST walker(BR, mgr.getAnalysisDeclContext(RD));
+
+    // Check the constructors.
+    for (CXXRecordDecl::ctor_iterator I = RD->ctor_begin(), E = RD->ctor_end();
+         I != E; ++I) {
+      if (!I->isCopyOrMoveConstructor())
+        if (Stmt *Body = I->getBody()) {
+          walker.Visit(Body);
+          walker.Execute();
+        }
+    }
+
+    // Check the destructor.
+    if (CXXDestructorDecl *DD = RD->getDestructor())
+      if (Stmt *Body = DD->getBody()) {
+        walker.Visit(Body);
+        walker.Execute();
+      }
+  }
+};
+}
+
+void ento::registerVirtualCallChecker(CheckerManager &mgr) {
+  mgr.registerChecker<VirtualCallChecker>();
+}
-- 
cgit v1.2.3