Index: lib/StaticAnalyzer/Checkers/CatchHandlerChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/CatchHandlerChecker.cpp	(revision 0)
+++ lib/StaticAnalyzer/Checkers/CatchHandlerChecker.cpp	(working copy)
@@ -0,0 +1,101 @@
+//==- CatchHandlerChecker.cpp - Check C++ try/catch block handlers*- 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 for C++ catch handlers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+  class WalkAST : public StmtVisitor<WalkAST> {
+    BugReporter &BR;
+    const CheckerBase *Checker;
+    AnalysisDeclContext* AC;
+
+  public:
+    WalkAST(BugReporter &br, const CheckerBase *checker, AnalysisDeclContext *ac)
+      : BR(br), Checker(checker), AC(ac) {}
+    void VisitStmt(Stmt *S) { VisitChildren(S); }
+    void VisitChildren(Stmt *S);
+    void VisitCXXTryStmt(CXXTryStmt *Stmt);
+  };
+}
+
+void WalkAST::VisitChildren(Stmt *S) {
+  for (auto *Child : S->children())
+    if (Child) Visit(Child);
+}
+
+static bool isDerivedFrom(const VarDecl *VD,
+                          const llvm::SmallVectorImpl<VarDecl *> &L) {
+  // We only care about situations where the compiler would have otherwise
+  // called this handler, except for derivation inversion. That means we only
+  // need to worry about pointers and references to C++ records.
+  const auto *InDecl = VD->getType()->getPointeeCXXRecordDecl();
+  if (!InDecl)
+    return false;
+
+  for (const auto *LD : L) {
+    if (const auto *TestDecl = LD->getType()->getPointeeCXXRecordDecl()) {
+      if (InDecl->isDerivedFrom(TestDecl))
+        return true;
+    }    
+  }
+  return false;
+}
+
+void WalkAST::VisitCXXTryStmt(CXXTryStmt *Stmt) {
+  // Walk over the catch handlers for this try statement. If a catch handler
+  // parameter type is a derived class of a handler parameter type seen
+  // previously, it will never be executed as a catch handler and we can
+  // diagnose it.
+  llvm::SmallVector<VarDecl *, 2> CatchParams;
+  for (unsigned I = 0, E = Stmt->getNumHandlers(); I != E; ++I) {
+    auto *VD = Stmt->getHandler(I)->getExceptionDecl();
+    if (isDerivedFrom(VD, CatchParams)) {
+      PathDiagnosticLocation ELoc =
+        PathDiagnosticLocation::createBegin(VD, BR.getSourceManager());
+      BR.EmitBasicReport(AC->getDecl(), Checker, "Catch Handler Inversion",
+                         categories::LogicError,
+                         "Catch handler will not be executed because a "
+                         "preceding catch handler parameter type is a base "
+                         "class of this catch handler parameter type.",
+                         ELoc, Stmt->getSourceRange());
+    }
+    CatchParams.push_back(VD);
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// CXXCatchHandlerChecker
+//===----------------------------------------------------------------------===//
+
+namespace {
+  class CXXCatchHandlerChecker : public Checker<check::ASTCodeBody> {
+  public:
+    void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
+                          BugReporter &BR) const {
+      WalkAST walker(BR, this, mgr.getAnalysisDeclContext(D));
+      walker.Visit(D->getBody());
+    }
+  };
+}
+
+void ento::registerCatchHandlerChecker(CheckerManager &mgr) {
+  mgr.registerChecker<CXXCatchHandlerChecker>();
+}
Index: lib/StaticAnalyzer/Checkers/Checkers.td
===================================================================
--- lib/StaticAnalyzer/Checkers/Checkers.td	(revision 220684)
+++ lib/StaticAnalyzer/Checkers/Checkers.td	(working copy)
@@ -188,6 +188,9 @@
   HelpText<"Check for memory leaks. Traces memory managed by new/delete.">, 
   DescFile<"MallocChecker.cpp">;
 
+def CatchHandlerChecker : Checker<"CatchHandler">,
+  HelpText<"Check catch handlers.">,
+  DescFile<"CatchHandlerChecker.cpp">;
 } // end: "cplusplus"
 
 let ParentPackage = CplusplusAlpha in {
Index: lib/StaticAnalyzer/Checkers/CMakeLists.txt
===================================================================
--- lib/StaticAnalyzer/Checkers/CMakeLists.txt	(revision 220684)
+++ lib/StaticAnalyzer/Checkers/CMakeLists.txt	(working copy)
@@ -15,6 +15,7 @@
   BasicObjCFoundationChecks.cpp
   BoolAssignmentChecker.cpp
   BuiltinFunctionChecker.cpp
+  CatchHandlerChecker.cpp
   CStringChecker.cpp
   CStringSyntaxChecker.cpp
   CallAndMessageChecker.cpp
Index: test/Analysis/cxx-catch-handlers.cpp
===================================================================
--- test/Analysis/cxx-catch-handlers.cpp	(revision 0)
+++ test/Analysis/cxx-catch-handlers.cpp	(working copy)
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -fcxx-exceptions -analyze -analyzer-checker=cplusplus -verify %s
+
+struct B {};
+struct D : B {};
+struct D2 : D {};
+
+void f1() {
+  try {
+  } catch (B &b) {
+  } catch (D &d) { // expected-warning {{Catch handler will not be executed}}
+  }
+}
+
+void f2() {
+  try {
+  } catch (B *b) {
+  } catch (D *d) { // expected-warning {{Catch handler will not be executed}}
+  }
+}
+
+void f3() {
+  try {
+  } catch (D &d) { // Ok
+  } catch (B &b) {
+  }
+}
+
+void f4() {
+  try {
+  } catch (B &b) { // Ok
+  }
+}
+
+void f5() {
+  try {
+  } catch (int) {
+  } catch (float ) {
+  }
+}
+
+void f6() {
+  try {
+  } catch (B &b) {
+  } catch (D2 &d) {  // expected-warning {{Catch handler will not be executed}}
+  }
+}
