Updated to Clang 3.5a.

Change-Id: I8127eb568f674c2e72635b639a3295381fe8af82
diff --git a/lib/Analysis/AnalysisDeclContext.cpp b/lib/Analysis/AnalysisDeclContext.cpp
index 465f0c3..c90d947 100644
--- a/lib/Analysis/AnalysisDeclContext.cpp
+++ b/lib/Analysis/AnalysisDeclContext.cpp
@@ -28,8 +28,8 @@
 #include "clang/Analysis/Support/BumpVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/SaveAndRestore.h"
+#include "llvm/Support/raw_ostream.h"
 
 using namespace clang;
 
@@ -68,7 +68,8 @@
                                                        bool addInitializers,
                                                        bool addTemporaryDtors,
                                                        bool synthesizeBodies,
-                                                       bool addStaticInitBranch)
+                                                       bool addStaticInitBranch,
+                                                       bool addCXXNewAllocator)
   : SynthesizeBodies(synthesizeBodies)
 {
   cfgBuildOptions.PruneTriviallyFalseEdges = !useUnoptimizedCFG;
@@ -76,12 +77,11 @@
   cfgBuildOptions.AddInitializers = addInitializers;
   cfgBuildOptions.AddTemporaryDtors = addTemporaryDtors;
   cfgBuildOptions.AddStaticInitBranches = addStaticInitBranch;
+  cfgBuildOptions.AddCXXNewAllocator = addCXXNewAllocator;
 }
 
 void AnalysisDeclContextManager::clear() {
-  for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
-    delete I->second;
-  Contexts.clear();
+  llvm::DeleteContainerSeconds(Contexts);
 }
 
 static BodyFarm &getBodyFarm(ASTContext &C) {
@@ -94,14 +94,21 @@
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
     Stmt *Body = FD->getBody();
     if (!Body && Manager && Manager->synthesizeBodies()) {
-      IsAutosynthesized = true;
-      return getBodyFarm(getASTContext()).getBody(FD);
+      Body = getBodyFarm(getASTContext()).getBody(FD);
+      if (Body)
+        IsAutosynthesized = true;
     }
     return Body;
   }
-  else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
-    return MD->getBody();
-  else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
+  else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+    Stmt *Body = MD->getBody();
+    if (!Body && Manager && Manager->synthesizeBodies()) {
+      Body = getBodyFarm(getASTContext()).getBody(MD);
+      if (Body)
+        IsAutosynthesized = true;
+    }
+    return Body;
+  } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
     return BD->getBody();
   else if (const FunctionTemplateDecl *FunTmpl
            = dyn_cast_or_null<FunctionTemplateDecl>(D))
@@ -126,9 +133,8 @@
     return MD->getSelfDecl();
   if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
     // See if 'self' was captured by the block.
-    for (BlockDecl::capture_const_iterator it = BD->capture_begin(),
-         et = BD->capture_end(); it != et; ++it) {
-      const VarDecl *VD = it->getVariable();
+    for (const auto &I : BD->captures()) {
+      const VarDecl *VD = I.getVariable();
       if (VD->getName() == "self")
         return dyn_cast<ImplicitParamDecl>(VD);
     }    
@@ -235,10 +241,8 @@
   if (!PM) {
     PM.reset(new ParentMap(getBody()));
     if (const CXXConstructorDecl *C = dyn_cast<CXXConstructorDecl>(getDecl())) {
-      for (CXXConstructorDecl::init_const_iterator I = C->init_begin(),
-                                                   E = C->init_end();
-           I != E; ++I) {
-        PM->addStmt((*I)->getInit());
+      for (const auto *I : C->inits()) {
+        PM->addStmt(I->getInit());
       }
     }
     if (builtCFG)
@@ -435,7 +439,7 @@
   }
 }
 
-void LocationContext::dumpStack() const {
+LLVM_DUMP_METHOD void LocationContext::dumpStack() const {
   dumpStack(llvm::errs());
 }
 
@@ -454,11 +458,6 @@
                             BumpVectorContext &bc)
   : BEVals(bevals), BC(bc) {}
 
-  bool IsTrackedDecl(const VarDecl *VD) {
-    const DeclContext *DC = VD->getDeclContext();
-    return IgnoredContexts.count(DC) == 0;
-  }
-
   void VisitStmt(Stmt *S) {
     for (Stmt::child_range I = S->children(); I; ++I)
       if (Stmt *child = *I)
@@ -506,9 +505,8 @@
   new (BV) DeclVec(BC, 10);
 
   // Go through the capture list.
-  for (BlockDecl::capture_const_iterator CI = BD->capture_begin(),
-       CE = BD->capture_end(); CI != CE; ++CI) {
-    BV->push_back(CI->getVariable(), BC);
+  for (const auto &CI : BD->captures()) {
+    BV->push_back(CI.getVariable(), BC);
   }
 
   // Find the referenced global/static variables.
@@ -548,15 +546,13 @@
   // Release the managed analyses.
   if (ManagedAnalyses) {
     ManagedAnalysisMap *M = (ManagedAnalysisMap*) ManagedAnalyses;
-    for (ManagedAnalysisMap::iterator I = M->begin(), E = M->end(); I!=E; ++I)
-      delete I->second;  
+    llvm::DeleteContainerSeconds(*M);
     delete M;
   }
 }
 
 AnalysisDeclContextManager::~AnalysisDeclContextManager() {
-  for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
-    delete I->second;
+  llvm::DeleteContainerSeconds(Contexts);
 }
 
 LocationContext::~LocationContext() {}
diff --git a/lib/Analysis/Android.mk b/lib/Analysis/Android.mk
index 8a73690..8ccbf3e 100644
--- a/lib/Analysis/Android.mk
+++ b/lib/Analysis/Android.mk
@@ -8,6 +8,7 @@
 TBLGEN_TABLES := \
   AttrList.inc \
   Attrs.inc \
+  AttrVisitor.inc \
   CommentCommandList.inc \
   CommentNodes.inc \
   DeclNodes.inc \
diff --git a/lib/Analysis/BodyFarm.cpp b/lib/Analysis/BodyFarm.cpp
index 4d5c2ee..039911e 100644
--- a/lib/Analysis/BodyFarm.cpp
+++ b/lib/Analysis/BodyFarm.cpp
@@ -35,8 +35,7 @@
   // returns void.
   const FunctionProtoType *FT =
   BPT->getPointeeType()->getAs<FunctionProtoType>();
-  if (!FT || !FT->getResultType()->isVoidType()  ||
-      FT->getNumArgs() != 0)
+  if (!FT || !FT->getReturnType()->isVoidType() || FT->getNumParams() != 0)
     return false;
 
   return true;
@@ -74,6 +73,9 @@
   
   /// Create an Objective-C bool literal.
   ObjCBoolLiteralExpr *makeObjCBool(bool Val);
+
+  /// Create an Objective-C ivar reference.
+  ObjCIvarRefExpr *makeObjCIvarRef(const Expr *Base, const ObjCIvarDecl *IVar);
   
   /// Create a Return statement.
   ReturnStmt *makeReturn(const Expr *RetVal);
@@ -147,6 +149,15 @@
   return new (C) ObjCBoolLiteralExpr(Val, Ty, SourceLocation());
 }
 
+ObjCIvarRefExpr *ASTMaker::makeObjCIvarRef(const Expr *Base,
+                                           const ObjCIvarDecl *IVar) {
+  return new (C) ObjCIvarRefExpr(const_cast<ObjCIvarDecl*>(IVar),
+                                 IVar->getType(), SourceLocation(),
+                                 SourceLocation(), const_cast<Expr*>(Base),
+                                 /*arrow=*/true, /*free=*/false);
+}
+
+
 ReturnStmt *ASTMaker::makeReturn(const Expr *RetVal) {
   return new (C) ReturnStmt(SourceLocation(), const_cast<Expr*>(RetVal), 0);
 }
@@ -278,8 +289,8 @@
   //    return YES;
   //   }
   //   else return NO;
-  
-  QualType ResultTy = D->getResultType();
+
+  QualType ResultTy = D->getReturnType();
   bool isBoolean = ResultTy->isBooleanType();
   if (!isBoolean && !ResultTy->isIntegralType(C))
     return 0;
@@ -374,3 +385,87 @@
   return Val.getValue();
 }
 
+static Stmt *createObjCPropertyGetter(ASTContext &Ctx,
+                                      const ObjCPropertyDecl *Prop) {
+  // First, find the backing ivar.
+  const ObjCIvarDecl *IVar = Prop->getPropertyIvarDecl();
+  if (!IVar)
+    return 0;
+
+  // Ignore weak variables, which have special behavior.
+  if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak)
+    return 0;
+
+  // Look to see if Sema has synthesized a body for us. This happens in
+  // Objective-C++ because the return value may be a C++ class type with a
+  // non-trivial copy constructor. We can only do this if we can find the
+  // @synthesize for this property, though (or if we know it's been auto-
+  // synthesized).
+  const ObjCImplementationDecl *ImplDecl =
+    IVar->getContainingInterface()->getImplementation();
+  if (ImplDecl) {
+    for (const auto *I : ImplDecl->property_impls()) {
+      if (I->getPropertyDecl() != Prop)
+        continue;
+
+      if (I->getGetterCXXConstructor()) {
+        ASTMaker M(Ctx);
+        return M.makeReturn(I->getGetterCXXConstructor());
+      }
+    }
+  }
+
+  // Sanity check that the property is the same type as the ivar, or a
+  // reference to it, and that it is either an object pointer or trivially
+  // copyable.
+  if (!Ctx.hasSameUnqualifiedType(IVar->getType(),
+                                  Prop->getType().getNonReferenceType()))
+    return 0;
+  if (!IVar->getType()->isObjCLifetimeType() &&
+      !IVar->getType().isTriviallyCopyableType(Ctx))
+    return 0;
+
+  // Generate our body:
+  //   return self->_ivar;
+  ASTMaker M(Ctx);
+
+  const VarDecl *selfVar = Prop->getGetterMethodDecl()->getSelfDecl();
+
+  Expr *loadedIVar =
+    M.makeObjCIvarRef(
+      M.makeLvalueToRvalue(
+        M.makeDeclRefExpr(selfVar),
+        selfVar->getType()),
+      IVar);
+
+  if (!Prop->getType()->isReferenceType())
+    loadedIVar = M.makeLvalueToRvalue(loadedIVar, IVar->getType());
+
+  return M.makeReturn(loadedIVar);
+}
+
+Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) {
+  // We currently only know how to synthesize property accessors.
+  if (!D->isPropertyAccessor())
+    return 0;
+
+  D = D->getCanonicalDecl();
+
+  Optional<Stmt *> &Val = Bodies[D];
+  if (Val.hasValue())
+    return Val.getValue();
+  Val = 0;
+
+  const ObjCPropertyDecl *Prop = D->findPropertyDecl();
+  if (!Prop)
+    return 0;
+
+  // For now, we only synthesize getters.
+  if (D->param_size() != 0)
+    return 0;
+
+  Val = createObjCPropertyGetter(C, Prop);
+
+  return Val.getValue();
+}
+
diff --git a/lib/Analysis/BodyFarm.h b/lib/Analysis/BodyFarm.h
index 96f61df..2d200fb 100644
--- a/lib/Analysis/BodyFarm.h
+++ b/lib/Analysis/BodyFarm.h
@@ -24,6 +24,8 @@
 class ASTContext;
 class Decl;
 class FunctionDecl;
+class ObjCMethodDecl;
+class ObjCPropertyDecl;
 class Stmt;
   
 class BodyFarm {
@@ -32,7 +34,10 @@
   
   /// Factory method for creating bodies for ordinary functions.
   Stmt *getBody(const FunctionDecl *D);
-  
+
+  /// Factory method for creating bodies for Objective-C properties.
+  Stmt *getBody(const ObjCMethodDecl *D);
+
 private:
   typedef llvm::DenseMap<const Decl *, Optional<Stmt *> > BodyMap;
 
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index 8b8c573..400c202 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -21,7 +21,7 @@
 #include "clang/AST/StmtVisitor.h"
 #include "clang/Basic/Builtins.h"
 #include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/OwningPtr.h"
+#include <memory>
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/Format.h"
@@ -291,7 +291,7 @@
   typedef BlockScopePosPair JumpSource;
 
   ASTContext *Context;
-  OwningPtr<CFG> cfg;
+  std::unique_ptr<CFG> cfg;
 
   CFGBlock *Block;
   CFGBlock *Succ;
@@ -363,6 +363,7 @@
                                       AddStmtChoice asc);
   CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S);
   CFGBlock *VisitCXXConstructExpr(CXXConstructExpr *C, AddStmtChoice asc);
+  CFGBlock *VisitCXXNewExpr(CXXNewExpr *DE, AddStmtChoice asc);
   CFGBlock *VisitCXXDeleteExpr(CXXDeleteExpr *DE, AddStmtChoice asc);
   CFGBlock *VisitCXXForRangeStmt(CXXForRangeStmt *S);
   CFGBlock *VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
@@ -459,6 +460,9 @@
   void appendInitializer(CFGBlock *B, CXXCtorInitializer *I) {
     B->appendInitializer(I, cfg->getBumpVectorContext());
   }
+  void appendNewAllocator(CFGBlock *B, CXXNewExpr *NE) {
+    B->appendNewAllocator(NE, cfg->getBumpVectorContext());
+  }
   void appendBaseDtor(CFGBlock *B, const CXXBaseSpecifier *BS) {
     B->appendBaseDtor(BS, cfg->getBumpVectorContext());
   }
@@ -479,8 +483,16 @@
   void prependAutomaticObjDtorsWithTerminator(CFGBlock *Blk,
       LocalScope::const_iterator B, LocalScope::const_iterator E);
 
-  void addSuccessor(CFGBlock *B, CFGBlock *S) {
-    B->addSuccessor(S, cfg->getBumpVectorContext());
+  void addSuccessor(CFGBlock *B, CFGBlock *S, bool IsReachable = true) {
+    B->addSuccessor(CFGBlock::AdjacentBlock(S, IsReachable),
+                    cfg->getBumpVectorContext());
+  }
+
+  /// Add a reachable successor to a block, with the alternate variant that is
+  /// unreachable.
+  void addSuccessor(CFGBlock *B, CFGBlock *ReachableBlock, CFGBlock *AltBlock) {
+    B->addSuccessor(CFGBlock::AdjacentBlock(ReachableBlock, AltBlock),
+                    cfg->getBumpVectorContext());
   }
 
   /// Try and evaluate an expression to an integer constant.
@@ -712,7 +724,7 @@
   // Create an empty entry block that has no predecessors.
   cfg->setEntry(createBlock());
 
-  return cfg.take();
+  return cfg.release();
 }
 
 /// createBlock - Used to lazily create blocks that are connected
@@ -730,7 +742,7 @@
 CFGBlock *CFGBuilder::createNoReturnBlock() {
   CFGBlock *B = createBlock(false);
   B->setHasNoReturnElement();
-  addSuccessor(B, &cfg->getExit());
+  addSuccessor(B, &cfg->getExit(), Succ);
   return B;
 }
 
@@ -868,30 +880,27 @@
   const CXXRecordDecl *RD = DD->getParent();
 
   // At the end destroy virtual base objects.
-  for (CXXRecordDecl::base_class_const_iterator VI = RD->vbases_begin(),
-      VE = RD->vbases_end(); VI != VE; ++VI) {
-    const CXXRecordDecl *CD = VI->getType()->getAsCXXRecordDecl();
+  for (const auto &VI : RD->vbases()) {
+    const CXXRecordDecl *CD = VI.getType()->getAsCXXRecordDecl();
     if (!CD->hasTrivialDestructor()) {
       autoCreateBlock();
-      appendBaseDtor(Block, VI);
+      appendBaseDtor(Block, &VI);
     }
   }
 
   // Before virtual bases destroy direct base objects.
-  for (CXXRecordDecl::base_class_const_iterator BI = RD->bases_begin(),
-      BE = RD->bases_end(); BI != BE; ++BI) {
-    if (!BI->isVirtual()) {
-      const CXXRecordDecl *CD = BI->getType()->getAsCXXRecordDecl();
+  for (const auto &BI : RD->bases()) {
+    if (!BI.isVirtual()) {
+      const CXXRecordDecl *CD = BI.getType()->getAsCXXRecordDecl();
       if (!CD->hasTrivialDestructor()) {
         autoCreateBlock();
-        appendBaseDtor(Block, BI);
+        appendBaseDtor(Block, &BI);
       }
     }
   }
 
   // First destroy member objects.
-  for (CXXRecordDecl::field_iterator FI = RD->field_begin(),
-      FE = RD->field_end(); FI != FE; ++FI) {
+  for (auto *FI : RD->fields()) {
     // Check for constant size array. Set type to array element type.
     QualType QT = FI->getType();
     if (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) {
@@ -903,7 +912,7 @@
     if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl())
       if (!CD->hasTrivialDestructor()) {
         autoCreateBlock();
-        appendMemberDtor(Block, *FI);
+        appendMemberDtor(Block, FI);
       }
   }
 }
@@ -930,9 +939,8 @@
 
   // For compound statement we will be creating explicit scope.
   if (CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
-    for (CompoundStmt::body_iterator BI = CS->body_begin(), BE = CS->body_end()
-        ; BI != BE; ++BI) {
-      Stmt *SI = (*BI)->stripLabelLikeStatements();
+    for (auto *BI : CS->body()) {
+      Stmt *SI = BI->stripLabelLikeStatements();
       if (DeclStmt *DS = dyn_cast<DeclStmt>(SI))
         Scope = addLocalScopeForDeclStmt(DS, Scope);
     }
@@ -952,11 +960,9 @@
   if (!BuildOpts.AddImplicitDtors)
     return Scope;
 
-  for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end()
-      ; DI != DE; ++DI) {
-    if (VarDecl *VD = dyn_cast<VarDecl>(*DI))
+  for (auto *DI : DS->decls())
+    if (VarDecl *VD = dyn_cast<VarDecl>(DI))
       Scope = addLocalScopeForVarDecl(VD, Scope);
-  }
   return Scope;
 }
 
@@ -1122,6 +1128,9 @@
     case Stmt::CXXConstructExprClass:
       return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc);
 
+    case Stmt::CXXNewExprClass:
+      return VisitCXXNewExpr(cast<CXXNewExpr>(S), asc);
+
     case Stmt::CXXDeleteExprClass:
       return VisitCXXDeleteExpr(cast<CXXDeleteExpr>(S), asc);
 
@@ -1293,7 +1302,7 @@
   do {
     if (BinaryOperator *B_RHS = dyn_cast<BinaryOperator>(RHS))
       if (B_RHS->isLogicalOp()) {
-        llvm::tie(RHSBlock, ExitBlock) =
+        std::tie(RHSBlock, ExitBlock) =
           VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock);
         break;
       }
@@ -1311,8 +1320,8 @@
     else {
       RHSBlock->setTerminator(Term);
       TryResult KnownVal = tryEvaluateBool(RHS);
-      addSuccessor(RHSBlock, KnownVal.isFalse() ? NULL : TrueBlock);
-      addSuccessor(RHSBlock, KnownVal.isTrue() ? NULL : FalseBlock);
+      addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse());
+      addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue());
     }
 
     Block = RHSBlock;
@@ -1355,12 +1364,12 @@
 
   // Now link the LHSBlock with RHSBlock.
   if (B->getOpcode() == BO_LOr) {
-    addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : TrueBlock);
-    addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : RHSBlock);
+    addSuccessor(LHSBlock, TrueBlock, !KnownVal.isFalse());
+    addSuccessor(LHSBlock, RHSBlock, !KnownVal.isTrue());
   } else {
     assert(B->getOpcode() == BO_LAnd);
-    addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock);
-    addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : FalseBlock);
+    addSuccessor(LHSBlock, RHSBlock, !KnownVal.isFalse());
+    addSuccessor(LHSBlock, FalseBlock, !KnownVal.isTrue());
   }
 
   return std::make_pair(EntryLHSBlock, ExitBlock);
@@ -1619,8 +1628,8 @@
 
   // See if this is a known constant.
   const TryResult& KnownVal = tryEvaluateBool(C->getCond());
-  addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock);
-  addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock);
+  addSuccessor(Block, LHSBlock, !KnownVal.isFalse());
+  addSuccessor(Block, RHSBlock, !KnownVal.isTrue());
   Block->setTerminator(C);
   Expr *condExpr = C->getCond();
 
@@ -1865,9 +1874,10 @@
   // See if this is a known constant.
   const TryResult &KnownVal = tryEvaluateBool(I->getCond());
 
-  // Now add the successors.
-  addSuccessor(Block, KnownVal.isFalse() ? NULL : ThenBlock);
-  addSuccessor(Block, KnownVal.isTrue()? NULL : ElseBlock);
+  // Add the successors.  If we know that specific branches are
+  // unreachable, inform addSuccessor() of that knowledge.
+  addSuccessor(Block, ThenBlock, /* isReachable = */ !KnownVal.isFalse());
+  addSuccessor(Block, ElseBlock, /* isReachable = */ !KnownVal.isTrue());
 
   // Add the condition as the last statement in the new block.  This may create
   // new blocks as the condition may contain control-flow.  Any newly created
@@ -2078,7 +2088,7 @@
     if (BinaryOperator *Cond =
             dyn_cast_or_null<BinaryOperator>(C ? C->IgnoreParens() : 0))
       if (Cond->isLogicalOp()) {
-        llvm::tie(EntryConditionBlock, ExitConditionBlock) =
+        std::tie(EntryConditionBlock, ExitConditionBlock) =
           VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor);
         break;
       }
@@ -2394,9 +2404,8 @@
     // more optimal CFG representation.
     if (BinaryOperator *Cond = dyn_cast<BinaryOperator>(C->IgnoreParens()))
       if (Cond->isLogicalOp()) {
-        llvm::tie(EntryConditionBlock, ExitConditionBlock) =
-          VisitLogicalOperator(Cond, W, BodyBlock,
-                               LoopSuccessor);
+        std::tie(EntryConditionBlock, ExitConditionBlock) =
+            VisitLogicalOperator(Cond, W, BodyBlock, LoopSuccessor);
         break;
       }
 
@@ -2726,8 +2735,8 @@
   SwitchAlwaysHasSuccessor |= switchExclusivelyCovered;
   SwitchAlwaysHasSuccessor |= Terminator->isAllEnumCasesCovered() &&
                               Terminator->getSwitchCaseList();
-  addSuccessor(SwitchTerminatedBlock,
-               SwitchAlwaysHasSuccessor ? 0 : DefaultCaseBlock);
+  addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock,
+               !SwitchAlwaysHasSuccessor);
 
   // Add the terminator and condition in the switch block.
   SwitchTerminatedBlock->setTerminator(Terminator);
@@ -2828,10 +2837,9 @@
   // Add this block to the list of successors for the block with the switch
   // statement.
   assert(SwitchTerminatedBlock);
-  addSuccessor(SwitchTerminatedBlock,
+  addSuccessor(SwitchTerminatedBlock, CaseBlock,
                shouldAddCase(switchExclusivelyCovered, switchCond,
-                             CS, *Context)
-               ? CaseBlock : 0);
+                             CS, *Context));
 
   // We set Block to NULL to allow lazy creation of a new block (if necessary)
   Block = NULL;
@@ -3124,6 +3132,23 @@
   return VisitChildren(C);
 }
 
+CFGBlock *CFGBuilder::VisitCXXNewExpr(CXXNewExpr *NE,
+                                      AddStmtChoice asc) {
+
+  autoCreateBlock();
+  appendStmt(Block, NE);
+
+  if (NE->getInitializer())
+    Block = Visit(NE->getInitializer());
+  if (BuildOpts.AddCXXNewAllocator)
+    appendNewAllocator(Block, NE);
+  if (NE->isArray())
+    Block = Visit(NE->getArraySize());
+  for (CXXNewExpr::arg_iterator I = NE->placement_arg_begin(),
+       E = NE->placement_arg_end(); I != E; ++I)
+    Block = Visit(*I);
+  return Block;
+}
 
 CFGBlock *CFGBuilder::VisitCXXDeleteExpr(CXXDeleteExpr *DE,
                                          AddStmtChoice asc) {
@@ -3320,10 +3345,12 @@
     // a new block for the destructor which does not have as a successor
     // anything built thus far. Control won't flow out of this block.
     const CXXDestructorDecl *Dtor = E->getTemporary()->getDestructor();
-    if (Dtor->isNoReturn())
+    if (Dtor->isNoReturn()) {
+      Succ = B;
       Block = createNoReturnBlock();
-    else
+    } else {
       autoCreateBlock();
+    }
 
     appendTemporaryDtor(Block, E);
     B = Block;
@@ -3372,12 +3399,13 @@
 
   Block = createBlock(false);
   Block->setTerminator(CFGTerminator(E, true));
+  assert(Block->getTerminator().isTemporaryDtorsBranch());
 
   // See if this is a known constant.
   const TryResult &KnownVal = tryEvaluateBool(E->getCond());
 
   if (LHSBlock) {
-    addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock);
+    addSuccessor(Block, LHSBlock, !KnownVal.isFalse());
   } else if (KnownVal.isFalse()) {
     addSuccessor(Block, NULL);
   } else {
@@ -3387,7 +3415,8 @@
 
   if (!RHSBlock)
     RHSBlock = ConfluenceBlock;
-  addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock);
+
+  addSuccessor(Block, RHSBlock, !KnownVal.isTrue());
 
   return Block;
 }
@@ -3426,6 +3455,7 @@
   switch (getKind()) {
     case CFGElement::Statement:
     case CFGElement::Initializer:
+    case CFGElement::NewAllocator:
       llvm_unreachable("getDestructorDecl should only be used with "
                        "ImplicitDtors");
     case CFGElement::AutomaticObjectDtor: {
@@ -3470,13 +3500,37 @@
 }
 
 //===----------------------------------------------------------------------===//
-// Filtered walking of the CFG.
+// CFGBlock operations.
 //===----------------------------------------------------------------------===//
 
+CFGBlock::AdjacentBlock::AdjacentBlock(CFGBlock *B, bool IsReachable)
+  : ReachableBlock(IsReachable ? B : 0),
+    UnreachableBlock(!IsReachable ? B : 0,
+                     B && IsReachable ? AB_Normal : AB_Unreachable) {}
+
+CFGBlock::AdjacentBlock::AdjacentBlock(CFGBlock *B, CFGBlock *AlternateBlock)
+  : ReachableBlock(B),
+    UnreachableBlock(B == AlternateBlock ? 0 : AlternateBlock,
+                     B == AlternateBlock ? AB_Alternate : AB_Normal) {}
+
+void CFGBlock::addSuccessor(AdjacentBlock Succ,
+                            BumpVectorContext &C) {
+  if (CFGBlock *B = Succ.getReachableBlock())
+    B->Preds.push_back(AdjacentBlock(this, Succ.isReachable()), C);
+
+  if (CFGBlock *UnreachableB = Succ.getPossiblyUnreachableBlock())
+    UnreachableB->Preds.push_back(AdjacentBlock(this, false), C);
+
+  Succs.push_back(Succ, C);
+}
+
 bool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F,
         const CFGBlock *From, const CFGBlock *To) {
 
-  if (To && F.IgnoreDefaultsWithCoveredEnums) {
+  if (F.IgnoreNullPredecessors && !From)
+    return true;
+
+  if (To && From && F.IgnoreDefaultsWithCoveredEnums) {
     // If the 'To' has no label or is labeled but the label isn't a
     // CaseStmt then filter this edge.
     if (const SwitchStmt *S =
@@ -3572,7 +3626,7 @@
   void setBlockID(signed i) { currentBlock = i; }
   void setStmtID(unsigned i) { currStmt = i; }
 
-  virtual bool handledStmt(Stmt *S, raw_ostream &OS) {
+  bool handledStmt(Stmt *S, raw_ostream &OS) override {
     StmtMapTy::iterator I = StmtMap.find(S);
 
     if (I == StmtMap.end())
@@ -3615,7 +3669,9 @@
 public:
   CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper,
                           const PrintingPolicy &Policy)
-    : OS(os), Helper(helper), Policy(Policy) {}
+    : OS(os), Helper(helper), Policy(Policy) {
+    this->Policy.IncludeNewlines = false;
+  }
 
   void VisitIfStmt(IfStmt *I) {
     OS << "if ";
@@ -3705,6 +3761,13 @@
   void VisitExpr(Expr *E) {
     E->printPretty(OS, Helper, Policy);
   }
+
+public:
+  void print(CFGTerminator T) {
+    if (T.isTemporaryDtorsBranch())
+      OS << "(Temp Dtor) ";
+    Visit(T.getStmt());
+  }
 };
 } // end anonymous namespace
 
@@ -3787,6 +3850,11 @@
     OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()";
     OS << " (Implicit destructor)\n";
 
+  } else if (Optional<CFGNewAllocator> NE = E.getAs<CFGNewAllocator>()) {
+    OS << "CFGNewAllocator(";
+    if (const CXXNewExpr *AllocExpr = NE->getAllocatorExpr())
+      AllocExpr->getType().print(OS, PrintingPolicy(Helper.getLangOpts()));
+    OS << ")\n";
   } else if (Optional<CFGDeleteDtor> DE = E.getAs<CFGDeleteDtor>()) {
     const CXXRecordDecl *RD = DE->getCXXRecordDecl();
     if (!RD)
@@ -3835,6 +3903,8 @@
     OS << " (EXIT)]\n";
   else if (&B == cfg->getIndirectGotoBlock())
     OS << " (INDIRECT GOTO DISPATCH)]\n";
+  else if (B.hasNoReturnElement())
+    OS << " (NORETURN)]\n";
   else
     OS << "]\n";
   
@@ -3903,7 +3973,7 @@
 
     PrintingPolicy PP(Helper.getLangOpts());
     CFGBlockTerminatorPrint TPrinter(OS, &Helper, PP);
-    TPrinter.Visit(const_cast<Stmt*>(B.getTerminator().getStmt()));
+    TPrinter.print(B.getTerminator());
     OS << '\n';
     
     if (ShowColors)
@@ -3931,7 +4001,16 @@
         if (i % 10 == 8)
           OS << "\n     ";
 
-        OS << " B" << (*I)->getBlockID();
+        CFGBlock *B = *I;
+        bool Reachable = true;
+        if (!B) {
+          Reachable = false;
+          B = I->getPossiblyUnreachableBlock();
+        }
+
+        OS << " B" << B->getBlockID();
+        if (!Reachable)
+          OS << "(Unreachable)";
       }
       
       if (ShowColors)
@@ -3960,12 +4039,24 @@
         if (i % 10 == 8)
           OS << "\n    ";
 
-        if (*I)
-          OS << " B" << (*I)->getBlockID();
-        else
-          OS  << " NULL";
+        CFGBlock *B = *I;
+
+        bool Reachable = true;
+        if (!B) {
+          Reachable = false;
+          B = I->getPossiblyUnreachableBlock();
+        }
+
+        if (B) {
+          OS << " B" << B->getBlockID();
+          if (!Reachable)
+            OS << "(Unreachable)";
+        }
+        else {
+          OS << " NULL";
+        }
       }
-      
+
       if (ShowColors)
         OS.resetColor();
       OS << '\n';
@@ -4020,10 +4111,10 @@
 void CFGBlock::printTerminator(raw_ostream &OS,
                                const LangOptions &LO) const {
   CFGBlockTerminatorPrint TPrinter(OS, NULL, PrintingPolicy(LO));
-  TPrinter.Visit(const_cast<Stmt*>(getTerminator().getStmt()));
+  TPrinter.print(getTerminator());
 }
 
-Stmt *CFGBlock::getTerminatorCondition() {
+Stmt *CFGBlock::getTerminatorCondition(bool StripParens) {
   Stmt *Terminator = this->Terminator;
   if (!Terminator)
     return NULL;
@@ -4082,6 +4173,9 @@
       return Terminator;
   }
 
+  if (!StripParens)
+    return E;
+
   return E ? E->IgnoreParens() : NULL;
 }
 
diff --git a/lib/Analysis/CFGReachabilityAnalysis.cpp b/lib/Analysis/CFGReachabilityAnalysis.cpp
index 492e66f..4ae135f 100644
--- a/lib/Analysis/CFGReachabilityAnalysis.cpp
+++ b/lib/Analysis/CFGReachabilityAnalysis.cpp
@@ -69,7 +69,8 @@
     // Add the predecessors to the worklist.
     for (CFGBlock::const_pred_iterator i = block->pred_begin(), 
          e = block->pred_end(); i != e; ++i) {
-      worklist.push_back(*i);
+      if (*i)
+        worklist.push_back(*i);
     }
   }
 }
diff --git a/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt
index deab8f1..9630bc0 100644
--- a/lib/Analysis/CMakeLists.txt
+++ b/lib/Analysis/CMakeLists.txt
@@ -1,3 +1,8 @@
+set(LLVM_LINK_COMPONENTS
+  MC
+  Support
+  )
+
 add_clang_library(clangAnalysis
   AnalysisDeclContext.cpp
   BodyFarm.cpp
@@ -19,19 +24,8 @@
   ScanfFormatString.cpp
   ThreadSafety.cpp
   UninitializedValues.cpp
-  )
 
-add_dependencies(clangAnalysis
-  ClangAttrClasses
-  ClangAttrList
-  ClangCommentNodes
-  ClangDiagnosticCommon
-  ClangDeclNodes
-  ClangDiagnosticAnalysis
-  ClangStmtNodes
-  )
-
-target_link_libraries(clangAnalysis
+  LINK_LIBS
   clangBasic
   clangAST
   )
diff --git a/lib/Analysis/CallGraph.cpp b/lib/Analysis/CallGraph.cpp
index 3387015..649ba57 100644
--- a/lib/Analysis/CallGraph.cpp
+++ b/lib/Analysis/CallGraph.cpp
@@ -95,9 +95,8 @@
   if (BlockDecl *BD = dyn_cast<BlockDecl>(D))
     addNodeForDecl(BD, true);
 
-  for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end();
-       I!=E; ++I)
-    if (DeclContext *DC = dyn_cast<DeclContext>(*I))
+  for (auto *I : D->decls())
+    if (auto *DC = dyn_cast<DeclContext>(I))
       addNodesForBlocks(DC);
 }
 
@@ -106,12 +105,7 @@
 }
 
 CallGraph::~CallGraph() {
-  if (!FunctionMap.empty()) {
-    for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end();
-        I != E; ++I)
-      delete I->second;
-    FunctionMap.clear();
-  }
+  llvm::DeleteContainerSeconds(FunctionMap);
 }
 
 bool CallGraph::includeInGraph(const Decl *D) {
diff --git a/lib/Analysis/Consumed.cpp b/lib/Analysis/Consumed.cpp
index b33c8d8..7b6ad57 100644
--- a/lib/Analysis/Consumed.cpp
+++ b/lib/Analysis/Consumed.cpp
@@ -17,20 +17,20 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/RecursiveASTVisitor.h"
-#include "clang/AST/StmtVisitor.h"
 #include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtVisitor.h"
 #include "clang/AST/Type.h"
+#include "clang/Analysis/Analyses/Consumed.h"
 #include "clang/Analysis/Analyses/PostOrderCFGView.h"
 #include "clang/Analysis/AnalysisContext.h"
 #include "clang/Analysis/CFG.h"
-#include "clang/Analysis/Analyses/Consumed.h"
 #include "clang/Basic/OperatorKinds.h"
 #include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/raw_ostream.h"
+#include <memory>
 
 // TODO: Adjust states of args to constructors in the same way that arguments to
 //       function calls are handled.
@@ -143,6 +143,7 @@
   return false;
 }
 
+
 static bool isConsumableType(const QualType &QT) {
   if (QT->isPointerType() || QT->isReferenceType())
     return false;
@@ -153,6 +154,23 @@
   return false;
 }
 
+static bool isAutoCastType(const QualType &QT) {
+  if (QT->isPointerType() || QT->isReferenceType())
+    return false;
+
+  if (const CXXRecordDecl *RD = QT->getAsCXXRecordDecl())
+    return RD->hasAttr<ConsumableAutoCastAttr>();
+
+  return false;
+}
+
+static bool isSetOnReadPtrType(const QualType &QT) {
+  if (const CXXRecordDecl *RD = QT->getPointeeCXXRecordDecl())
+    return RD->hasAttr<ConsumableSetOnReadAttr>();
+  return false;
+}
+
+
 static bool isKnownState(ConsumedState State) {
   switch (State) {
   case CS_Unconsumed:
@@ -165,19 +183,16 @@
   llvm_unreachable("invalid enum");
 }
 
-static bool isRValueRefish(QualType ParamType) {
-  return ParamType->isRValueReferenceType() ||
-        (ParamType->isLValueReferenceType() &&
-         !cast<LValueReferenceType>(
-           ParamType.getCanonicalType())->isSpelledAsLValue());
+static bool isRValueRef(QualType ParamType) {
+  return ParamType->isRValueReferenceType();
 }
 
 static bool isTestingFunction(const FunctionDecl *FunDecl) {
   return FunDecl->hasAttr<TestTypestateAttr>();
 }
 
-static bool isValueType(QualType ParamType) {
-  return !(ParamType->isPointerType() || ParamType->isReferenceType());
+static bool isPointerOrRef(QualType ParamType) {
+  return ParamType->isPointerType() || ParamType->isReferenceType();
 }
 
 static ConsumedState mapConsumableAttrState(const QualType QT) {
@@ -455,15 +470,29 @@
   ConsumedAnalyzer &Analyzer;
   ConsumedStateMap *StateMap;
   MapType PropagationMap;
-  void forwardInfo(const Stmt *From, const Stmt *To);
-  bool isLikeMoveAssignment(const CXXMethodDecl *MethodDecl);
-  void propagateReturnType(const Stmt *Call, const FunctionDecl *Fun,
-                           QualType ReturnType);
+
+  InfoEntry findInfo(const Expr *E) {
+    return PropagationMap.find(E->IgnoreParens());
+  }
+  ConstInfoEntry findInfo(const Expr *E) const {
+    return PropagationMap.find(E->IgnoreParens());
+  }
+  void insertInfo(const Expr *E, const PropagationInfo &PI) {
+    PropagationMap.insert(PairType(E->IgnoreParens(), PI));
+  }
+
+  void forwardInfo(const Expr *From, const Expr *To);
+  void copyInfo(const Expr *From, const Expr *To, ConsumedState CS);
+  ConsumedState getInfo(const Expr *From);
+  void setInfo(const Expr *To, ConsumedState NS);
+  void propagateReturnType(const Expr *Call, const FunctionDecl *Fun);
 
 public:
   void checkCallability(const PropagationInfo &PInfo,
                         const FunctionDecl *FunDecl,
                         SourceLocation BlameLoc);
+  bool handleCall(const CallExpr *Call, const Expr *ObjArg,
+                  const FunctionDecl *FunD);
   
   void VisitBinaryOperator(const BinaryOperator *BinOp);
   void VisitCallExpr(const CallExpr *Call);
@@ -485,8 +514,8 @@
                       ConsumedStateMap *StateMap)
       : AC(AC), Analyzer(Analyzer), StateMap(StateMap) {}
   
-  PropagationInfo getInfo(const Stmt *StmtNode) const {
-    ConstInfoEntry Entry = PropagationMap.find(StmtNode);
+  PropagationInfo getInfo(const Expr *StmtNode) const {
+    ConstInfoEntry Entry = findInfo(StmtNode);
     
     if (Entry != PropagationMap.end())
       return Entry->second;
@@ -499,76 +528,187 @@
   }
 };
 
+
+void ConsumedStmtVisitor::forwardInfo(const Expr *From, const Expr *To) {
+  InfoEntry Entry = findInfo(From);
+  if (Entry != PropagationMap.end())
+    insertInfo(To, Entry->second);
+}
+
+
+// Create a new state for To, which is initialized to the state of From.
+// If NS is not CS_None, sets the state of From to NS.
+void ConsumedStmtVisitor::copyInfo(const Expr *From, const Expr *To,
+                                   ConsumedState NS) {
+  InfoEntry Entry = findInfo(From);
+  if (Entry != PropagationMap.end()) {
+    PropagationInfo& PInfo = Entry->second;
+    ConsumedState CS = PInfo.getAsState(StateMap);
+    if (CS != CS_None)
+      insertInfo(To, PropagationInfo(CS));
+    if (NS != CS_None && PInfo.isPointerToValue())
+      setStateForVarOrTmp(StateMap, PInfo, NS);
+  }
+}
+
+
+// Get the ConsumedState for From
+ConsumedState ConsumedStmtVisitor::getInfo(const Expr *From) {
+  InfoEntry Entry = findInfo(From);
+  if (Entry != PropagationMap.end()) {
+    PropagationInfo& PInfo = Entry->second;
+    return PInfo.getAsState(StateMap);
+  }
+  return CS_None;
+}
+
+
+// If we already have info for To then update it, otherwise create a new entry.
+void ConsumedStmtVisitor::setInfo(const Expr *To, ConsumedState NS) {
+  InfoEntry Entry = findInfo(To);
+  if (Entry != PropagationMap.end()) {
+    PropagationInfo& PInfo = Entry->second;
+    if (PInfo.isPointerToValue())
+      setStateForVarOrTmp(StateMap, PInfo, NS);
+  } else if (NS != CS_None) {
+     insertInfo(To, PropagationInfo(NS));
+  }
+}
+
+
+
 void ConsumedStmtVisitor::checkCallability(const PropagationInfo &PInfo,
                                            const FunctionDecl *FunDecl,
                                            SourceLocation BlameLoc) {
   assert(!PInfo.isTest());
-  
-  if (!FunDecl->hasAttr<CallableWhenAttr>())
-    return;
-  
+
   const CallableWhenAttr *CWAttr = FunDecl->getAttr<CallableWhenAttr>();
-  
+  if (!CWAttr)
+    return;
+
   if (PInfo.isVar()) {
     ConsumedState VarState = StateMap->getState(PInfo.getVar());
-    
+
     if (VarState == CS_None || isCallableInState(CWAttr, VarState))
       return;
-    
+
     Analyzer.WarningsHandler.warnUseInInvalidState(
       FunDecl->getNameAsString(), PInfo.getVar()->getNameAsString(),
       stateToString(VarState), BlameLoc);
-    
+
   } else {
     ConsumedState TmpState = PInfo.getAsState(StateMap);
-    
+
     if (TmpState == CS_None || isCallableInState(CWAttr, TmpState))
       return;
-    
+
     Analyzer.WarningsHandler.warnUseOfTempInInvalidState(
       FunDecl->getNameAsString(), stateToString(TmpState), BlameLoc);
   }
 }
 
-void ConsumedStmtVisitor::forwardInfo(const Stmt *From, const Stmt *To) {
-  InfoEntry Entry = PropagationMap.find(From);
-  
-  if (Entry != PropagationMap.end())
-    PropagationMap.insert(PairType(To, Entry->second));
+
+// Factors out common behavior for function, method, and operator calls.
+// Check parameters and set parameter state if necessary.
+// Returns true if the state of ObjArg is set, or false otherwise.
+bool ConsumedStmtVisitor::handleCall(const CallExpr *Call, const Expr *ObjArg,
+                                     const FunctionDecl *FunD) {
+  unsigned Offset = 0;
+  if (isa<CXXOperatorCallExpr>(Call) && isa<CXXMethodDecl>(FunD))
+    Offset = 1;  // first argument is 'this'
+
+  // check explicit parameters
+  for (unsigned Index = Offset; Index < Call->getNumArgs(); ++Index) {
+    // Skip variable argument lists.
+    if (Index - Offset >= FunD->getNumParams())
+      break;
+
+    const ParmVarDecl *Param = FunD->getParamDecl(Index - Offset);
+    QualType ParamType = Param->getType();
+
+    InfoEntry Entry = findInfo(Call->getArg(Index));
+
+    if (Entry == PropagationMap.end() || Entry->second.isTest())
+      continue;
+    PropagationInfo PInfo = Entry->second;
+
+    // Check that the parameter is in the correct state.
+    if (ParamTypestateAttr *PTA = Param->getAttr<ParamTypestateAttr>()) {
+      ConsumedState ParamState = PInfo.getAsState(StateMap);
+      ConsumedState ExpectedState = mapParamTypestateAttrState(PTA);
+
+      if (ParamState != ExpectedState)
+        Analyzer.WarningsHandler.warnParamTypestateMismatch(
+          Call->getArg(Index)->getExprLoc(),
+          stateToString(ExpectedState), stateToString(ParamState));
+    }
+
+    if (!(Entry->second.isVar() || Entry->second.isTmp()))
+      continue;
+
+    // Adjust state on the caller side.
+    if (isRValueRef(ParamType))
+      setStateForVarOrTmp(StateMap, PInfo, consumed::CS_Consumed);
+    else if (ReturnTypestateAttr *RT = Param->getAttr<ReturnTypestateAttr>())
+      setStateForVarOrTmp(StateMap, PInfo, mapReturnTypestateAttrState(RT));
+    else if (isPointerOrRef(ParamType) &&
+             (!ParamType->getPointeeType().isConstQualified() ||
+              isSetOnReadPtrType(ParamType)))
+      setStateForVarOrTmp(StateMap, PInfo, consumed::CS_Unknown);
+  }
+
+  if (!ObjArg)
+    return false;
+
+  // check implicit 'self' parameter, if present
+  InfoEntry Entry = findInfo(ObjArg);
+  if (Entry != PropagationMap.end()) {
+    PropagationInfo PInfo = Entry->second;
+    checkCallability(PInfo, FunD, Call->getExprLoc());
+
+    if (SetTypestateAttr *STA = FunD->getAttr<SetTypestateAttr>()) {
+      if (PInfo.isVar()) {
+        StateMap->setState(PInfo.getVar(), mapSetTypestateAttrState(STA));
+        return true;
+      }
+      else if (PInfo.isTmp()) {
+        StateMap->setState(PInfo.getTmp(), mapSetTypestateAttrState(STA));
+        return true;
+      }
+    }
+    else if (isTestingFunction(FunD) && PInfo.isVar()) {
+      PropagationMap.insert(PairType(Call,
+        PropagationInfo(PInfo.getVar(), testsFor(FunD))));
+    }
+  }
+  return false;
 }
 
-bool ConsumedStmtVisitor::isLikeMoveAssignment(
-  const CXXMethodDecl *MethodDecl) {
-  
-  return MethodDecl->isMoveAssignmentOperator() ||
-         (MethodDecl->getOverloadedOperator() == OO_Equal &&
-          MethodDecl->getNumParams() == 1 &&
-          MethodDecl->getParamDecl(0)->getType()->isRValueReferenceType());
-}
 
-void ConsumedStmtVisitor::propagateReturnType(const Stmt *Call,
-                                              const FunctionDecl *Fun,
-                                              QualType ReturnType) {
-  if (isConsumableType(ReturnType)) {
-    
+void ConsumedStmtVisitor::propagateReturnType(const Expr *Call,
+                                              const FunctionDecl *Fun) {
+  QualType RetType = Fun->getCallResultType();
+  if (RetType->isReferenceType())
+    RetType = RetType->getPointeeType();
+
+  if (isConsumableType(RetType)) {
     ConsumedState ReturnState;
-    
-    if (Fun->hasAttr<ReturnTypestateAttr>())
-      ReturnState = mapReturnTypestateAttrState(
-        Fun->getAttr<ReturnTypestateAttr>());
+    if (ReturnTypestateAttr *RTA = Fun->getAttr<ReturnTypestateAttr>())
+      ReturnState = mapReturnTypestateAttrState(RTA);
     else
-      ReturnState = mapConsumableAttrState(ReturnType);
+      ReturnState = mapConsumableAttrState(RetType);
     
     PropagationMap.insert(PairType(Call, PropagationInfo(ReturnState)));
   }
 }
 
+
 void ConsumedStmtVisitor::VisitBinaryOperator(const BinaryOperator *BinOp) {
   switch (BinOp->getOpcode()) {
   case BO_LAnd:
   case BO_LOr : {
-    InfoEntry LEntry = PropagationMap.find(BinOp->getLHS()),
-              REntry = PropagationMap.find(BinOp->getRHS());
+    InfoEntry LEntry = findInfo(BinOp->getLHS()),
+              REntry = findInfo(BinOp->getRHS());
     
     VarTestResult LTest, RTest;
     
@@ -605,69 +745,32 @@
   }
 }
 
+static bool isStdNamespace(const DeclContext *DC) {
+  if (!DC->isNamespace()) return false;
+  while (DC->getParent()->isNamespace())
+    DC = DC->getParent();
+  const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC);
+
+  return ND && ND->getName() == "std" &&
+         ND->getDeclContext()->isTranslationUnit();
+}
+
 void ConsumedStmtVisitor::VisitCallExpr(const CallExpr *Call) {
-  if (const FunctionDecl *FunDecl =
-    dyn_cast_or_null<FunctionDecl>(Call->getDirectCallee())) {
-    
-    // Special case for the std::move function.
-    // TODO: Make this more specific. (Deferred)
-    if (FunDecl->getNameAsString() == "move") {
-      forwardInfo(Call->getArg(0), Call);
-      return;
-    }
-    
-    unsigned Offset = Call->getNumArgs() - FunDecl->getNumParams();
-    
-    for (unsigned Index = Offset; Index < Call->getNumArgs(); ++Index) {
-      const ParmVarDecl *Param = FunDecl->getParamDecl(Index - Offset);
-      QualType ParamType = Param->getType();
-      
-      InfoEntry Entry = PropagationMap.find(Call->getArg(Index));
-      
-      if (Entry == PropagationMap.end() || Entry->second.isTest())
-        continue;
-      
-      PropagationInfo PInfo = Entry->second;
-      
-      // Check that the parameter is in the correct state.
-      
-      if (Param->hasAttr<ParamTypestateAttr>()) {
-        ConsumedState ParamState = PInfo.getAsState(StateMap);
-        
-        ConsumedState ExpectedState =
-          mapParamTypestateAttrState(Param->getAttr<ParamTypestateAttr>());
-        
-        if (ParamState != ExpectedState)
-          Analyzer.WarningsHandler.warnParamTypestateMismatch(
-            Call->getArg(Index - Offset)->getExprLoc(),
-            stateToString(ExpectedState), stateToString(ParamState));
-      }
-      
-      if (!(Entry->second.isVar() || Entry->second.isTmp()))
-        continue;
-      
-      // Adjust state on the caller side.
-      
-      if (isRValueRefish(ParamType)) {
-        setStateForVarOrTmp(StateMap, PInfo, consumed::CS_Consumed);
-        
-      } else if (Param->hasAttr<ReturnTypestateAttr>()) {
-        setStateForVarOrTmp(StateMap, PInfo,
-          mapReturnTypestateAttrState(Param->getAttr<ReturnTypestateAttr>()));
-        
-      } else if (!isValueType(ParamType) &&
-                 !ParamType->getPointeeType().isConstQualified()) {
-        
-        setStateForVarOrTmp(StateMap, PInfo, consumed::CS_Unknown);
-      }
-    }
-    
-    QualType RetType = FunDecl->getCallResultType();
-    if (RetType->isReferenceType())
-      RetType = RetType->getPointeeType();
-    
-    propagateReturnType(Call, FunDecl, RetType);
+  const FunctionDecl *FunDecl = Call->getDirectCallee();
+  if (!FunDecl)
+    return;
+
+  // Special case for the std::move function.
+  // TODO: Make this more specific. (Deferred)
+  if (Call->getNumArgs() == 1 &&
+      FunDecl->getNameAsString() == "move" &&
+      isStdNamespace(FunDecl->getDeclContext())) {
+    copyInfo(Call->getArg(0), Call, CS_Consumed);
+    return;
   }
+
+  handleCall(Call, 0, FunDecl);
+  propagateReturnType(Call, FunDecl);
 }
 
 void ConsumedStmtVisitor::VisitCastExpr(const CastExpr *Cast) {
@@ -677,7 +780,7 @@
 void ConsumedStmtVisitor::VisitCXXBindTemporaryExpr(
   const CXXBindTemporaryExpr *Temp) {
   
-  InfoEntry Entry = PropagationMap.find(Temp->getSubExpr());
+  InfoEntry Entry = findInfo(Temp->getSubExpr());
   
   if (Entry != PropagationMap.end() && !Entry->second.isTest()) {
     StateMap->setState(Temp, Entry->second.getAsState(StateMap));
@@ -695,168 +798,60 @@
     return;
   
   // FIXME: What should happen if someone annotates the move constructor?
-  if (Constructor->hasAttr<ReturnTypestateAttr>()) {
-    // TODO: Adjust state of args appropriately.
-    
-    ReturnTypestateAttr *RTAttr = Constructor->getAttr<ReturnTypestateAttr>();
-    ConsumedState RetState = mapReturnTypestateAttrState(RTAttr);
+  if (ReturnTypestateAttr *RTA = Constructor->getAttr<ReturnTypestateAttr>()) {
+    // TODO: Adjust state of args appropriately.    
+    ConsumedState RetState = mapReturnTypestateAttrState(RTA);
     PropagationMap.insert(PairType(Call, PropagationInfo(RetState)));
-    
   } else if (Constructor->isDefaultConstructor()) {
-    
     PropagationMap.insert(PairType(Call,
       PropagationInfo(consumed::CS_Consumed)));
-    
   } else if (Constructor->isMoveConstructor()) {
-    
-    InfoEntry Entry = PropagationMap.find(Call->getArg(0));
-    
-    if (Entry != PropagationMap.end()) {
-      PropagationInfo PInfo = Entry->second;
-      
-      if (PInfo.isVar()) {
-        const VarDecl* Var = PInfo.getVar();
-        
-        PropagationMap.insert(PairType(Call,
-          PropagationInfo(StateMap->getState(Var))));
-        
-        StateMap->setState(Var, consumed::CS_Consumed);
-        
-      } else if (PInfo.isTmp()) {
-        const CXXBindTemporaryExpr *Tmp = PInfo.getTmp();
-        
-        PropagationMap.insert(PairType(Call,
-          PropagationInfo(StateMap->getState(Tmp))));
-        
-        StateMap->setState(Tmp, consumed::CS_Consumed);
-        
-      } else {
-        PropagationMap.insert(PairType(Call, PInfo));
-      }
-    }
+    copyInfo(Call->getArg(0), Call, CS_Consumed);
   } else if (Constructor->isCopyConstructor()) {
-    forwardInfo(Call->getArg(0), Call);
-    
+    // Copy state from arg.  If setStateOnRead then set arg to CS_Unknown.
+    ConsumedState NS =
+      isSetOnReadPtrType(Constructor->getThisType(CurrContext)) ?
+      CS_Unknown : CS_None;
+    copyInfo(Call->getArg(0), Call, NS);
   } else {
     // TODO: Adjust state of args appropriately.
-    
     ConsumedState RetState = mapConsumableAttrState(ThisType);
     PropagationMap.insert(PairType(Call, PropagationInfo(RetState)));
   }
 }
 
+
 void ConsumedStmtVisitor::VisitCXXMemberCallExpr(
-  const CXXMemberCallExpr *Call) {
-  
-  VisitCallExpr(Call);
-  
-  InfoEntry Entry = PropagationMap.find(Call->getCallee()->IgnoreParens());
-  
-  if (Entry != PropagationMap.end()) {
-    PropagationInfo PInfo = Entry->second;
-    const CXXMethodDecl *MethodDecl = Call->getMethodDecl();
-    
-    checkCallability(PInfo, MethodDecl, Call->getExprLoc());
-    
-    if (PInfo.isVar()) {
-      if (isTestingFunction(MethodDecl))
-        PropagationMap.insert(PairType(Call,
-          PropagationInfo(PInfo.getVar(), testsFor(MethodDecl))));
-      else if (MethodDecl->hasAttr<SetTypestateAttr>())
-        StateMap->setState(PInfo.getVar(),
-          mapSetTypestateAttrState(MethodDecl->getAttr<SetTypestateAttr>()));
-    } else if (PInfo.isTmp() && MethodDecl->hasAttr<SetTypestateAttr>()) {
-      StateMap->setState(PInfo.getTmp(),
-        mapSetTypestateAttrState(MethodDecl->getAttr<SetTypestateAttr>()));
-    }
-  }
+    const CXXMemberCallExpr *Call) {
+  CXXMethodDecl* MD = Call->getMethodDecl();
+  if (!MD)
+    return;
+
+  handleCall(Call, Call->getImplicitObjectArgument(), MD);
+  propagateReturnType(Call, MD);
 }
 
+
 void ConsumedStmtVisitor::VisitCXXOperatorCallExpr(
-  const CXXOperatorCallExpr *Call) {
-  
+    const CXXOperatorCallExpr *Call) {
+
   const FunctionDecl *FunDecl =
     dyn_cast_or_null<FunctionDecl>(Call->getDirectCallee());
-  
   if (!FunDecl) return;
-    
-  if (isa<CXXMethodDecl>(FunDecl) &&
-      isLikeMoveAssignment(cast<CXXMethodDecl>(FunDecl))) {
-    
-    InfoEntry LEntry = PropagationMap.find(Call->getArg(0));
-    InfoEntry REntry = PropagationMap.find(Call->getArg(1));
-    
-    PropagationInfo LPInfo, RPInfo;
-    
-    if (LEntry != PropagationMap.end() &&
-        REntry != PropagationMap.end()) {
-      
-      LPInfo = LEntry->second;
-      RPInfo = REntry->second;
-      
-      if (LPInfo.isPointerToValue() && RPInfo.isPointerToValue()) {
-        setStateForVarOrTmp(StateMap, LPInfo, RPInfo.getAsState(StateMap));
-        PropagationMap.insert(PairType(Call, LPInfo));
-        setStateForVarOrTmp(StateMap, RPInfo, consumed::CS_Consumed);
-        
-      } else if (RPInfo.isState()) {
-        setStateForVarOrTmp(StateMap, LPInfo, RPInfo.getState());
-        PropagationMap.insert(PairType(Call, LPInfo));
-        
-      } else {
-        setStateForVarOrTmp(StateMap, RPInfo, consumed::CS_Consumed);
-      }
-      
-    } else if (LEntry != PropagationMap.end() &&
-               REntry == PropagationMap.end()) {
-      
-      LPInfo = LEntry->second;
-      
-      assert(!LPInfo.isTest());
-      
-      if (LPInfo.isPointerToValue()) {
-        setStateForVarOrTmp(StateMap, LPInfo, consumed::CS_Unknown);
-        PropagationMap.insert(PairType(Call, LPInfo));
-        
-      } else {
-        PropagationMap.insert(PairType(Call,
-          PropagationInfo(consumed::CS_Unknown)));
-      }
-      
-    } else if (LEntry == PropagationMap.end() &&
-               REntry != PropagationMap.end()) {
-      
-      RPInfo = REntry->second;
-      
-      if (RPInfo.isPointerToValue())
-        setStateForVarOrTmp(StateMap, RPInfo, consumed::CS_Consumed);
-    }
-    
-  } else {
-    
-    VisitCallExpr(Call);
-    
-    InfoEntry Entry = PropagationMap.find(Call->getArg(0));
-    
-    if (Entry != PropagationMap.end()) {
-      PropagationInfo PInfo = Entry->second;
-      
-      checkCallability(PInfo, FunDecl, Call->getExprLoc());
-      
-      if (PInfo.isVar()) {
-        if (isTestingFunction(FunDecl))
-          PropagationMap.insert(PairType(Call,
-            PropagationInfo(PInfo.getVar(), testsFor(FunDecl))));
-        else if (FunDecl->hasAttr<SetTypestateAttr>())
-          StateMap->setState(PInfo.getVar(),
-            mapSetTypestateAttrState(FunDecl->getAttr<SetTypestateAttr>()));
-        
-      } else if (PInfo.isTmp() && FunDecl->hasAttr<SetTypestateAttr>()) {
-        StateMap->setState(PInfo.getTmp(),
-          mapSetTypestateAttrState(FunDecl->getAttr<SetTypestateAttr>()));
-    }
-    }
+
+  if (Call->getOperator() == OO_Equal) {
+    ConsumedState CS = getInfo(Call->getArg(1));
+    if (!handleCall(Call, Call->getArg(0), FunDecl))
+      setInfo(Call->getArg(0), CS);
+    return;
   }
+
+  if (const CXXMemberCallExpr *MCall = dyn_cast<CXXMemberCallExpr>(Call))
+    handleCall(MCall, MCall->getImplicitObjectArgument(), FunDecl);
+  else
+    handleCall(Call, Call->getArg(0), FunDecl);
+
+  propagateReturnType(Call, FunDecl);
 }
 
 void ConsumedStmtVisitor::VisitDeclRefExpr(const DeclRefExpr *DeclRef) {
@@ -866,11 +861,9 @@
 }
 
 void ConsumedStmtVisitor::VisitDeclStmt(const DeclStmt *DeclS) {
-  for (DeclStmt::const_decl_iterator DI = DeclS->decl_begin(),
-       DE = DeclS->decl_end(); DI != DE; ++DI) {
-    
-    if (isa<VarDecl>(*DI)) VisitVarDecl(cast<VarDecl>(*DI));
-  }
+  for (const auto *DI : DeclS->decls())    
+    if (isa<VarDecl>(DI))
+      VisitVarDecl(cast<VarDecl>(DI));
   
   if (DeclS->isSingleDecl())
     if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(DeclS->getSingleDecl()))
@@ -892,22 +885,16 @@
   QualType ParamType = Param->getType();
   ConsumedState ParamState = consumed::CS_None;
   
-  if (Param->hasAttr<ParamTypestateAttr>()) {
-    const ParamTypestateAttr *PTAttr = Param->getAttr<ParamTypestateAttr>();
-    ParamState = mapParamTypestateAttrState(PTAttr);
-    
-  } else if (isConsumableType(ParamType)) {
-    ParamState = mapConsumableAttrState(ParamType);
-    
-  } else if (isRValueRefish(ParamType) &&
-             isConsumableType(ParamType->getPointeeType())) {
-    
-    ParamState = mapConsumableAttrState(ParamType->getPointeeType());
-    
-  } else if (ParamType->isReferenceType() &&
-             isConsumableType(ParamType->getPointeeType())) {
+  if (const ParamTypestateAttr *PTA = Param->getAttr<ParamTypestateAttr>())
+    ParamState = mapParamTypestateAttrState(PTA);    
+  else if (isConsumableType(ParamType))
+    ParamState = mapConsumableAttrState(ParamType);    
+  else if (isRValueRef(ParamType) &&
+           isConsumableType(ParamType->getPointeeType()))
+    ParamState = mapConsumableAttrState(ParamType->getPointeeType());    
+  else if (ParamType->isReferenceType() &&
+           isConsumableType(ParamType->getPointeeType()))
     ParamState = consumed::CS_Unknown;
-  }
   
   if (ParamState != CS_None)
     StateMap->setState(Param, ParamState);
@@ -917,7 +904,7 @@
   ConsumedState ExpectedState = Analyzer.getExpectedReturnState();
   
   if (ExpectedState != CS_None) {
-    InfoEntry Entry = PropagationMap.find(Ret->getRetValue());
+    InfoEntry Entry = findInfo(Ret->getRetValue());
     
     if (Entry != PropagationMap.end()) {
       ConsumedState RetState = Entry->second.getAsState(StateMap);
@@ -934,7 +921,7 @@
 }
 
 void ConsumedStmtVisitor::VisitUnaryOperator(const UnaryOperator *UOp) {
-  InfoEntry Entry = PropagationMap.find(UOp->getSubExpr()->IgnoreParens());
+  InfoEntry Entry = findInfo(UOp->getSubExpr());
   if (Entry == PropagationMap.end()) return;
   
   switch (UOp->getOpcode()) {
@@ -956,8 +943,7 @@
 void ConsumedStmtVisitor::VisitVarDecl(const VarDecl *Var) {
   if (isConsumableType(Var->getType())) {
     if (Var->hasInit()) {
-      MapType::iterator VIT = PropagationMap.find(
-        Var->getInit()->IgnoreImplicit());
+      MapType::iterator VIT = findInfo(Var->getInit()->IgnoreImplicit());
       if (VIT != PropagationMap.end()) {
         PropagationInfo PInfo = VIT->second;
         ConsumedState St = PInfo.getAsState(StateMap);
@@ -1158,24 +1144,21 @@
 void ConsumedStateMap::checkParamsForReturnTypestate(SourceLocation BlameLoc,
   ConsumedWarningsHandlerBase &WarningsHandler) const {
   
-  ConsumedState ExpectedState;
-  
   for (VarMapType::const_iterator DMI = VarMap.begin(), DME = VarMap.end();
        DMI != DME; ++DMI) {
     
     if (isa<ParmVarDecl>(DMI->first)) {
       const ParmVarDecl *Param = cast<ParmVarDecl>(DMI->first);
+      const ReturnTypestateAttr *RTA = Param->getAttr<ReturnTypestateAttr>();
       
-      if (!Param->hasAttr<ReturnTypestateAttr>()) continue;
+      if (!RTA)
+        continue;
       
-      ExpectedState =
-        mapReturnTypestateAttrState(Param->getAttr<ReturnTypestateAttr>());
-      
-      if (DMI->second != ExpectedState) {
+      ConsumedState ExpectedState = mapReturnTypestateAttrState(RTA);      
+      if (DMI->second != ExpectedState)
         WarningsHandler.warnParamReturnTypestateMismatch(BlameLoc,
           Param->getNameAsString(), stateToString(ExpectedState),
           stateToString(DMI->second));
-      }
     }
   }
 }
@@ -1286,9 +1269,7 @@
   } else
     ReturnType = D->getCallResultType();
 
-  if (D->hasAttr<ReturnTypestateAttr>()) {
-    const ReturnTypestateAttr *RTSAttr = D->getAttr<ReturnTypestateAttr>();
-
+  if (const ReturnTypestateAttr *RTSAttr = D->getAttr<ReturnTypestateAttr>()) {
     const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl();
     if (!RD || !RD->hasAttr<ConsumableAttr>()) {
       // FIXME: This should be removed when template instantiation propagates
@@ -1300,22 +1281,27 @@
       ExpectedReturnState = CS_None;
     } else
       ExpectedReturnState = mapReturnTypestateAttrState(RTSAttr);
-  } else if (isConsumableType(ReturnType))
-    ExpectedReturnState = mapConsumableAttrState(ReturnType);
+  } else if (isConsumableType(ReturnType)) {
+    if (isAutoCastType(ReturnType))   // We can auto-cast the state to the
+      ExpectedReturnState = CS_None;  // expected state.
+    else
+      ExpectedReturnState = mapConsumableAttrState(ReturnType);
+  }
   else
     ExpectedReturnState = CS_None;
 }
 
 bool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock,
                                   const ConsumedStmtVisitor &Visitor) {
-  
-  OwningPtr<ConsumedStateMap> FalseStates(new ConsumedStateMap(*CurrStates));
+
+  std::unique_ptr<ConsumedStateMap> FalseStates(
+      new ConsumedStateMap(*CurrStates));
   PropagationInfo PInfo;
   
   if (const IfStmt *IfNode =
     dyn_cast_or_null<IfStmt>(CurrBlock->getTerminator().getStmt())) {
     
-    const Stmt *Cond = IfNode->getCond();
+    const Expr *Cond = IfNode->getCond();
     
     PInfo = Visitor.getInfo(Cond);
     if (!PInfo.isValid() && isa<BinaryOperator>(Cond))
@@ -1384,8 +1370,8 @@
     delete CurrStates;
     
   if (*++SI)
-    BlockInfo.addInfo(*SI, FalseStates.take());
-  
+    BlockInfo.addInfo(*SI, FalseStates.release());
+
   CurrStates = NULL;
   return true;
 }
@@ -1410,9 +1396,8 @@
   ConsumedStmtVisitor Visitor(AC, *this, CurrStates);
   
   // Add all trackable parameters to the state map.
-  for (FunctionDecl::param_const_iterator PI = D->param_begin(),
-       PE = D->param_end(); PI != PE; ++PI) {
-    Visitor.VisitParmVarDecl(*PI);
+  for (auto PI : D->params()) {
+    Visitor.VisitParmVarDecl(PI);
   }
   
   // Visit all of the function's basic blocks.
diff --git a/lib/Analysis/LiveVariables.cpp b/lib/Analysis/LiveVariables.cpp
index 9e5ec55..b26d4fb 100644
--- a/lib/Analysis/LiveVariables.cpp
+++ b/lib/Analysis/LiveVariables.cpp
@@ -37,7 +37,6 @@
       POV(Ctx.getAnalysis<PostOrderCFGView>()) {}
   
   void enqueueBlock(const CFGBlock *block);
-  void enqueueSuccessors(const CFGBlock *block);
   void enqueuePredecessors(const CFGBlock *block);
 
   const CFGBlock *dequeue();
@@ -53,19 +52,6 @@
     worklist.push_back(block);
   }
 }
-  
-void DataflowWorklist::enqueueSuccessors(const clang::CFGBlock *block) {
-  const unsigned OldWorklistSize = worklist.size();
-  for (CFGBlock::const_succ_iterator I = block->succ_begin(),
-       E = block->succ_end(); I != E; ++I) {
-    enqueueBlock(*I);
-  }
-
-  if (OldWorklistSize == 0 || OldWorklistSize == worklist.size())
-    return;
-
-  sortWorklist();
-}
 
 void DataflowWorklist::enqueuePredecessors(const clang::CFGBlock *block) {
   const unsigned OldWorklistSize = worklist.size();
@@ -372,7 +358,7 @@
 
 void TransferFunctions::VisitBlockExpr(BlockExpr *BE) {
   AnalysisDeclContext::referenced_decls_iterator I, E;
-  llvm::tie(I, E) =
+  std::tie(I, E) =
     LV.analysisContext.getReferencedBlockVars(BE->getBlockDecl());
   for ( ; I != E ; ++I) {
     const VarDecl *VD = *I;
@@ -389,9 +375,8 @@
 }
 
 void TransferFunctions::VisitDeclStmt(DeclStmt *DS) {
-  for (DeclStmt::decl_iterator DI=DS->decl_begin(), DE = DS->decl_end();
-       DI != DE; ++DI)
-    if (VarDecl *VD = dyn_cast<VarDecl>(*DI)) {
+  for (const auto *DI : DS->decls())
+    if (const auto *VD = dyn_cast<VarDecl>(DI)) {
       if (!isAlwaysAlive(VD))
         val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
     }
@@ -581,16 +566,6 @@
   return new LiveVariables(LV);
 }
 
-static bool compare_entries(const CFGBlock *A, const CFGBlock *B) {
-  return A->getBlockID() < B->getBlockID();
-}
-
-static bool compare_vd_entries(const Decl *A, const Decl *B) {
-  SourceLocation ALoc = A->getLocStart();
-  SourceLocation BLoc = B->getLocStart();
-  return ALoc.getRawEncoding() < BLoc.getRawEncoding();
-}
-
 void LiveVariables::dumpBlockLiveness(const SourceManager &M) {
   getImpl(impl).dumpBlockLiveness(M);
 }
@@ -602,7 +577,9 @@
        it != ei; ++it) {
     vec.push_back(it->first);    
   }
-  std::sort(vec.begin(), vec.end(), compare_entries);
+  std::sort(vec.begin(), vec.end(), [](const CFGBlock *A, const CFGBlock *B) {
+    return A->getBlockID() < B->getBlockID();
+  });
 
   std::vector<const VarDecl*> declVec;
 
@@ -619,9 +596,11 @@
           se = vals.liveDecls.end(); si != se; ++si) {
       declVec.push_back(*si);      
     }
-    
-    std::sort(declVec.begin(), declVec.end(), compare_vd_entries);
-    
+
+    std::sort(declVec.begin(), declVec.end(), [](const Decl *A, const Decl *B) {
+      return A->getLocStart() < B->getLocStart();
+    });
+
     for (std::vector<const VarDecl*>::iterator di = declVec.begin(),
          de = declVec.end(); di != de; ++di) {
       llvm::errs() << " " << (*di)->getDeclName().getAsString()
diff --git a/lib/Analysis/NOTICE b/lib/Analysis/NOTICE
deleted file mode 100644
index 369204e..0000000
--- a/lib/Analysis/NOTICE
+++ /dev/null
@@ -1,62 +0,0 @@
-==============================================================================
-LLVM Release License
-==============================================================================
-University of Illinois/NCSA
-Open Source License
-
-Copyright (c) 2007-2011 University of Illinois at Urbana-Champaign.
-All rights reserved.
-
-Developed by:
-
-    LLVM Team
-
-    University of Illinois at Urbana-Champaign
-
-    http://llvm.org
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal with
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimers.
-
-    * Redistributions in binary form must reproduce the above copyright notice,
-      this list of conditions and the following disclaimers in the
-      documentation and/or other materials provided with the distribution.
-
-    * Neither the names of the LLVM Team, University of Illinois at
-      Urbana-Champaign, nor the names of its contributors may be used to
-      endorse or promote products derived from this Software without specific
-      prior written permission.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
-SOFTWARE.
-
-==============================================================================
-The LLVM software contains code written by third parties.  Such software will
-have its own individual LICENSE.TXT file in the directory in which it appears.
-This file will describe the copyrights, license, and restrictions which apply
-to that code.
-
-The disclaimer of warranty in the University of Illinois Open Source License
-applies to all code in the LLVM Distribution, and nothing in any of the
-other licenses gives permission to use the names of the LLVM Team or the
-University of Illinois to endorse or promote products derived from this
-Software.
-
-The following pieces of software have additional or alternate copyrights,
-licenses, and/or restrictions:
-
-Program             Directory
--------             ---------
-<none yet>
diff --git a/lib/Analysis/ProgramPoint.cpp b/lib/Analysis/ProgramPoint.cpp
index 7d67e8a..26b59bb 100644
--- a/lib/Analysis/ProgramPoint.cpp
+++ b/lib/Analysis/ProgramPoint.cpp
@@ -43,9 +43,10 @@
   }
 }
 
-SimpleProgramPointTag::SimpleProgramPointTag(StringRef description)
-  : desc(description) {}
+SimpleProgramPointTag::SimpleProgramPointTag(StringRef MsgProvider, 
+                                             StringRef Msg)
+  : Desc((MsgProvider + " : " + Msg).str()) {}
 
 StringRef SimpleProgramPointTag::getTagDescription() const {
-  return desc;
+  return Desc;
 }
diff --git a/lib/Analysis/PseudoConstantAnalysis.cpp b/lib/Analysis/PseudoConstantAnalysis.cpp
index 5d659ce..314ce7c 100644
--- a/lib/Analysis/PseudoConstantAnalysis.cpp
+++ b/lib/Analysis/PseudoConstantAnalysis.cpp
@@ -171,10 +171,9 @@
     case Stmt::DeclStmtClass: {
       const DeclStmt *DS = cast<DeclStmt>(Head);
       // Iterate over each decl and see if any of them contain reference decls
-      for (DeclStmt::const_decl_iterator I = DS->decl_begin(),
-          E = DS->decl_end(); I != E; ++I) {
+      for (const auto *I : DS->decls()) {
         // We only care about VarDecls
-        const VarDecl *VD = dyn_cast<VarDecl>(*I);
+        const VarDecl *VD = dyn_cast<VarDecl>(I);
         if (!VD)
           continue;
 
diff --git a/lib/Analysis/ReachableCode.cpp b/lib/Analysis/ReachableCode.cpp
index a2d19c0..3cc8ae4 100644
--- a/lib/Analysis/ReachableCode.cpp
+++ b/lib/Analysis/ReachableCode.cpp
@@ -13,10 +13,12 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Analysis/Analyses/ReachableCode.h"
+#include "clang/Lex/Preprocessor.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/StmtCXX.h"
+#include "clang/AST/ParentMap.h"
 #include "clang/Analysis/AnalysisContext.h"
 #include "clang/Analysis/CFG.h"
 #include "clang/Basic/SourceManager.h"
@@ -25,36 +27,324 @@
 
 using namespace clang;
 
-namespace {
-class DeadCodeScan {
-  llvm::BitVector Visited;
-  llvm::BitVector &Reachable;
-  SmallVector<const CFGBlock *, 10> WorkList;
-  
-  typedef SmallVector<std::pair<const CFGBlock *, const Stmt *>, 12>
-      DeferredLocsTy;
-  
-  DeferredLocsTy DeferredLocs;
-  
-public:
-  DeadCodeScan(llvm::BitVector &reachable)
-    : Visited(reachable.size()),
-      Reachable(reachable) {}
-  
-  void enqueue(const CFGBlock *block);  
-  unsigned scanBackwards(const CFGBlock *Start,
-                         clang::reachable_code::Callback &CB);
-  
-  bool isDeadCodeRoot(const CFGBlock *Block);
-  
-  const Stmt *findDeadCode(const CFGBlock *Block);
-  
-  void reportDeadCode(const Stmt *S,
-                      clang::reachable_code::Callback &CB);
-};
+//===----------------------------------------------------------------------===//
+// Core Reachability Analysis routines.
+//===----------------------------------------------------------------------===//
+
+static bool isEnumConstant(const Expr *Ex) {
+  const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex);
+  if (!DR)
+    return false;
+  return isa<EnumConstantDecl>(DR->getDecl());
 }
 
-void DeadCodeScan::enqueue(const CFGBlock *block) {  
+static bool isTrivialExpression(const Expr *Ex) {
+  Ex = Ex->IgnoreParenCasts();
+  return isa<IntegerLiteral>(Ex) || isa<StringLiteral>(Ex) ||
+         isa<CXXBoolLiteralExpr>(Ex) || isa<ObjCBoolLiteralExpr>(Ex) ||
+         isa<CharacterLiteral>(Ex) ||
+         isEnumConstant(Ex);
+}
+
+static bool isTrivialDoWhile(const CFGBlock *B, const Stmt *S) {
+  // Check if the block ends with a do...while() and see if 'S' is the
+  // condition.
+  if (const Stmt *Term = B->getTerminator()) {
+    if (const DoStmt *DS = dyn_cast<DoStmt>(Term)) {
+      const Expr *Cond = DS->getCond()->IgnoreParenCasts();
+      return Cond == S && isTrivialExpression(Cond);
+    }
+  }
+  return false;
+}
+
+static bool isDeadReturn(const CFGBlock *B, const Stmt *S) {
+  // Look to see if the block ends with a 'return', and see if 'S'
+  // is a substatement.  The 'return' may not be the last element in
+  // the block because of destructors.
+  for (CFGBlock::const_reverse_iterator I = B->rbegin(), E = B->rend();
+       I != E; ++I) {
+    if (Optional<CFGStmt> CS = I->getAs<CFGStmt>()) {
+      if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(CS->getStmt())) {
+        if (RS == S)
+          return true;
+        if (const Expr *RE = RS->getRetValue()) {
+          RE = RE->IgnoreParenCasts();
+          if (RE == S)
+            return true;
+          ParentMap PM(const_cast<Expr*>(RE));
+          // If 'S' is in the ParentMap, it is a subexpression of
+          // the return statement.  Note also that we are restricting
+          // to looking at return statements in the same CFGBlock,
+          // so this will intentionally not catch cases where the
+          // return statement contains nested control-flow.
+          return PM.getParent(S);
+        }
+      }
+      break;
+    }
+  }
+  return false;
+}
+
+static SourceLocation getTopMostMacro(SourceLocation Loc, SourceManager &SM) {
+  assert(Loc.isMacroID());
+  SourceLocation Last;
+  while (Loc.isMacroID()) {
+    Last = Loc;
+    Loc = SM.getImmediateMacroCallerLoc(Loc);
+  }
+  return Last;
+}
+
+/// Returns true if the statement is expanded from a configuration macro.
+static bool isExpandedFromConfigurationMacro(const Stmt *S,
+                                             Preprocessor &PP,
+                                             bool IgnoreYES_NO = false) {
+  // FIXME: This is not very precise.  Here we just check to see if the
+  // value comes from a macro, but we can do much better.  This is likely
+  // to be over conservative.  This logic is factored into a separate function
+  // so that we can refine it later.
+  SourceLocation L = S->getLocStart();
+  if (L.isMacroID()) {
+    if (IgnoreYES_NO) {
+      // The Objective-C constant 'YES' and 'NO'
+      // are defined as macros.  Do not treat them
+      // as configuration values.
+      SourceManager &SM = PP.getSourceManager();
+      SourceLocation TopL = getTopMostMacro(L, SM);
+      StringRef MacroName = PP.getImmediateMacroName(TopL);
+      if (MacroName == "YES" || MacroName == "NO")
+        return false;
+    }
+    return true;
+  }
+  return false;
+}
+
+static bool isConfigurationValue(const ValueDecl *D, Preprocessor &PP);
+
+/// Returns true if the statement represents a configuration value.
+///
+/// A configuration value is something usually determined at compile-time
+/// to conditionally always execute some branch.  Such guards are for
+/// "sometimes unreachable" code.  Such code is usually not interesting
+/// to report as unreachable, and may mask truly unreachable code within
+/// those blocks.
+static bool isConfigurationValue(const Stmt *S,
+                                 Preprocessor &PP,
+                                 SourceRange *SilenceableCondVal = nullptr,
+                                 bool IncludeIntegers = true,
+                                 bool WrappedInParens = false) {
+  if (!S)
+    return false;
+
+  // Special case looking for the sigil '()' around an integer literal.
+  if (const ParenExpr *PE = dyn_cast<ParenExpr>(S))
+    if (!PE->getLocStart().isMacroID())
+      return isConfigurationValue(PE->getSubExpr(), PP, SilenceableCondVal, 
+                                  IncludeIntegers, true);
+
+  if (const Expr *Ex = dyn_cast<Expr>(S))
+    S = Ex->IgnoreParenCasts();
+
+  bool IgnoreYES_NO = false;
+
+  switch (S->getStmtClass()) {
+    case Stmt::CallExprClass: {
+      const FunctionDecl *Callee =
+        dyn_cast_or_null<FunctionDecl>(cast<CallExpr>(S)->getCalleeDecl());
+      return Callee ? Callee->isConstexpr() : false;
+    }
+    case Stmt::DeclRefExprClass:
+      return isConfigurationValue(cast<DeclRefExpr>(S)->getDecl(), PP);
+    case Stmt::ObjCBoolLiteralExprClass:
+      IgnoreYES_NO = true;
+      // Fallthrough.
+    case Stmt::CXXBoolLiteralExprClass:
+    case Stmt::IntegerLiteralClass: {
+      const Expr *E = cast<Expr>(S);
+      if (IncludeIntegers) {
+        if (SilenceableCondVal && !SilenceableCondVal->getBegin().isValid())
+          *SilenceableCondVal = E->getSourceRange();
+        return WrappedInParens || isExpandedFromConfigurationMacro(E, PP, IgnoreYES_NO);
+      }
+      return false;
+    }
+    case Stmt::MemberExprClass:
+      return isConfigurationValue(cast<MemberExpr>(S)->getMemberDecl(), PP);
+    case Stmt::UnaryExprOrTypeTraitExprClass:
+      return true;
+    case Stmt::BinaryOperatorClass: {
+      const BinaryOperator *B = cast<BinaryOperator>(S);
+      // Only include raw integers (not enums) as configuration
+      // values if they are used in a logical or comparison operator
+      // (not arithmetic).
+      IncludeIntegers &= (B->isLogicalOp() || B->isComparisonOp());
+      return isConfigurationValue(B->getLHS(), PP, SilenceableCondVal,
+                                  IncludeIntegers) ||
+             isConfigurationValue(B->getRHS(), PP, SilenceableCondVal,
+                                  IncludeIntegers);
+    }
+    case Stmt::UnaryOperatorClass: {
+      const UnaryOperator *UO = cast<UnaryOperator>(S);
+      if (SilenceableCondVal) 
+        *SilenceableCondVal = UO->getSourceRange();      
+      return UO->getOpcode() == UO_LNot &&
+             isConfigurationValue(UO->getSubExpr(), PP, SilenceableCondVal,
+                                  IncludeIntegers, WrappedInParens);
+    }
+    default:
+      return false;
+  }
+}
+
+static bool isConfigurationValue(const ValueDecl *D, Preprocessor &PP) {
+  if (const EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(D))
+    return isConfigurationValue(ED->getInitExpr(), PP);
+  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    // As a heuristic, treat globals as configuration values.  Note
+    // that we only will get here if Sema evaluated this
+    // condition to a constant expression, which means the global
+    // had to be declared in a way to be a truly constant value.
+    // We could generalize this to local variables, but it isn't
+    // clear if those truly represent configuration values that
+    // gate unreachable code.
+    if (!VD->hasLocalStorage())
+      return true;
+
+    // As a heuristic, locals that have been marked 'const' explicitly
+    // can be treated as configuration values as well.
+    return VD->getType().isLocalConstQualified();
+  }
+  return false;
+}
+
+/// Returns true if we should always explore all successors of a block.
+static bool shouldTreatSuccessorsAsReachable(const CFGBlock *B,
+                                             Preprocessor &PP) {
+  if (const Stmt *Term = B->getTerminator()) {
+    if (isa<SwitchStmt>(Term))
+      return true;
+    // Specially handle '||' and '&&'.
+    if (isa<BinaryOperator>(Term)) {
+      return isConfigurationValue(Term, PP);
+    }
+  }
+
+  const Stmt *Cond = B->getTerminatorCondition(/* stripParens */ false);
+  return isConfigurationValue(Cond, PP);
+}
+
+static unsigned scanFromBlock(const CFGBlock *Start,
+                              llvm::BitVector &Reachable,
+                              Preprocessor *PP,
+                              bool IncludeSometimesUnreachableEdges) {
+  unsigned count = 0;
+  
+  // Prep work queue
+  SmallVector<const CFGBlock*, 32> WL;
+  
+  // The entry block may have already been marked reachable
+  // by the caller.
+  if (!Reachable[Start->getBlockID()]) {
+    ++count;
+    Reachable[Start->getBlockID()] = true;
+  }
+  
+  WL.push_back(Start);
+  
+  // Find the reachable blocks from 'Start'.
+  while (!WL.empty()) {
+    const CFGBlock *item = WL.pop_back_val();
+
+    // There are cases where we want to treat all successors as reachable.
+    // The idea is that some "sometimes unreachable" code is not interesting,
+    // and that we should forge ahead and explore those branches anyway.
+    // This allows us to potentially uncover some "always unreachable" code
+    // within the "sometimes unreachable" code.
+    // Look at the successors and mark then reachable.
+    Optional<bool> TreatAllSuccessorsAsReachable;
+    if (!IncludeSometimesUnreachableEdges)
+      TreatAllSuccessorsAsReachable = false;
+
+    for (CFGBlock::const_succ_iterator I = item->succ_begin(), 
+         E = item->succ_end(); I != E; ++I) {
+      const CFGBlock *B = *I;
+      if (!B) do {
+        const CFGBlock *UB = I->getPossiblyUnreachableBlock();
+        if (!UB)
+          break;
+
+        if (!TreatAllSuccessorsAsReachable.hasValue()) {
+          assert(PP);
+          TreatAllSuccessorsAsReachable =
+            shouldTreatSuccessorsAsReachable(item, *PP);
+        }
+
+        if (TreatAllSuccessorsAsReachable.getValue()) {
+          B = UB;
+          break;
+        }
+      }
+      while (false);
+
+      if (B) {
+        unsigned blockID = B->getBlockID();
+        if (!Reachable[blockID]) {
+          Reachable.set(blockID);
+          WL.push_back(B);
+          ++count;
+        }
+      }
+    }
+  }
+  return count;
+}
+
+static unsigned scanMaybeReachableFromBlock(const CFGBlock *Start,
+                                            Preprocessor &PP,
+                                            llvm::BitVector &Reachable) {
+  return scanFromBlock(Start, Reachable, &PP, true);
+}
+
+//===----------------------------------------------------------------------===//
+// Dead Code Scanner.
+//===----------------------------------------------------------------------===//
+
+namespace {
+  class DeadCodeScan {
+    llvm::BitVector Visited;
+    llvm::BitVector &Reachable;
+    SmallVector<const CFGBlock *, 10> WorkList;
+    Preprocessor &PP;
+
+    typedef SmallVector<std::pair<const CFGBlock *, const Stmt *>, 12>
+    DeferredLocsTy;
+
+    DeferredLocsTy DeferredLocs;
+
+  public:
+    DeadCodeScan(llvm::BitVector &reachable, Preprocessor &PP)
+    : Visited(reachable.size()),
+      Reachable(reachable),
+      PP(PP) {}
+
+    void enqueue(const CFGBlock *block);
+    unsigned scanBackwards(const CFGBlock *Start,
+    clang::reachable_code::Callback &CB);
+
+    bool isDeadCodeRoot(const CFGBlock *Block);
+
+    const Stmt *findDeadCode(const CFGBlock *Block);
+
+    void reportDeadCode(const CFGBlock *B,
+                        const Stmt *S,
+                        clang::reachable_code::Callback &CB);
+  };
+}
+
+void DeadCodeScan::enqueue(const CFGBlock *block) {
   unsigned blockID = block->getBlockID();
   if (Reachable[blockID] || Visited[blockID])
     return;
@@ -64,9 +354,9 @@
 
 bool DeadCodeScan::isDeadCodeRoot(const clang::CFGBlock *Block) {
   bool isDeadRoot = true;
-  
+
   for (CFGBlock::const_pred_iterator I = Block->pred_begin(),
-        E = Block->pred_end(); I != E; ++I) {
+       E = Block->pred_end(); I != E; ++I) {
     if (const CFGBlock *PredBlock = *I) {
       unsigned blockID = PredBlock->getBlockID();
       if (Visited[blockID]) {
@@ -81,7 +371,7 @@
       }
     }
   }
-  
+
   return isDeadRoot;
 }
 
@@ -100,11 +390,13 @@
       if (isValidDeadStmt(S))
         return S;
     }
-  
+
   if (CFGTerminator T = Block->getTerminator()) {
-    const Stmt *S = T.getStmt();
-    if (isValidDeadStmt(S))
-      return S;    
+    if (!T.isTemporaryDtorsBranch()) {
+      const Stmt *S = T.getStmt();
+      if (isValidDeadStmt(S))
+        return S;
+    }
   }
 
   return 0;
@@ -124,7 +416,7 @@
 
   unsigned count = 0;
   enqueue(Start);
-  
+
   while (!WorkList.empty()) {
     const CFGBlock *Block = WorkList.pop_back_val();
 
@@ -135,7 +427,7 @@
 
     // Look for any dead code within the block.
     const Stmt *S = findDeadCode(Block);
-    
+
     if (!S) {
       // No dead code.  Possibly an empty block.  Look at dead predecessors.
       for (CFGBlock::const_pred_iterator I = Block->pred_begin(),
@@ -145,16 +437,16 @@
       }
       continue;
     }
-    
+
     // Specially handle macro-expanded code.
     if (S->getLocStart().isMacroID()) {
-      count += clang::reachable_code::ScanReachableFromBlock(Block, Reachable);
+      count += scanMaybeReachableFromBlock(Block, PP, Reachable);
       continue;
     }
 
     if (isDeadCodeRoot(Block)) {
-      reportDeadCode(S, CB);
-      count += clang::reachable_code::ScanReachableFromBlock(Block, Reachable);
+      reportDeadCode(Block, S, CB);
+      count += scanMaybeReachableFromBlock(Block, PP, Reachable);
     }
     else {
       // Record this statement as the possibly best location in a
@@ -169,15 +461,15 @@
   if (!DeferredLocs.empty()) {
     llvm::array_pod_sort(DeferredLocs.begin(), DeferredLocs.end(), SrcCmp);
     for (DeferredLocsTy::iterator I = DeferredLocs.begin(),
-          E = DeferredLocs.end(); I != E; ++I) {
-      const CFGBlock *block = I->first;
-      if (Reachable[block->getBlockID()])
+         E = DeferredLocs.end(); I != E; ++I) {
+      const CFGBlock *Block = I->first;
+      if (Reachable[Block->getBlockID()])
         continue;
-      reportDeadCode(I->second, CB);
-      count += clang::reachable_code::ScanReachableFromBlock(block, Reachable);
+      reportDeadCode(Block, I->second, CB);
+      count += scanMaybeReachableFromBlock(Block, PP, Reachable);
     }
   }
-    
+
   return count;
 }
 
@@ -208,7 +500,7 @@
     case Expr::BinaryConditionalOperatorClass:
     case Expr::ConditionalOperatorClass: {
       const AbstractConditionalOperator *CO =
-        cast<AbstractConditionalOperator>(S);
+      cast<AbstractConditionalOperator>(S);
       return CO->getQuestionLoc();
     }
     case Expr::MemberExprClass: {
@@ -246,61 +538,86 @@
   return S->getLocStart();
 }
 
-void DeadCodeScan::reportDeadCode(const Stmt *S,
+void DeadCodeScan::reportDeadCode(const CFGBlock *B,
+                                  const Stmt *S,
                                   clang::reachable_code::Callback &CB) {
+  // Classify the unreachable code found, or suppress it in some cases.
+  reachable_code::UnreachableKind UK = reachable_code::UK_Other;
+
+  if (isa<BreakStmt>(S)) {
+    UK = reachable_code::UK_Break;
+  }
+  else if (isTrivialDoWhile(B, S)) {
+    return;
+  }
+  else if (isDeadReturn(B, S)) {
+    UK = reachable_code::UK_Return;
+  }
+
+  SourceRange SilenceableCondVal;
+
+  if (UK == reachable_code::UK_Other) {
+    // Check if the dead code is part of the "loop target" of
+    // a for/for-range loop.  This is the block that contains
+    // the increment code.
+    if (const Stmt *LoopTarget = B->getLoopTarget()) {
+      SourceLocation Loc = LoopTarget->getLocStart();
+      SourceRange R1(Loc, Loc), R2;
+
+      if (const ForStmt *FS = dyn_cast<ForStmt>(LoopTarget)) {
+        const Expr *Inc = FS->getInc();
+        Loc = Inc->getLocStart();
+        R2 = Inc->getSourceRange();
+      }
+
+      CB.HandleUnreachable(reachable_code::UK_Loop_Increment,
+                           Loc, SourceRange(), SourceRange(Loc, Loc), R2);
+      return;
+    }
+    
+    // Check if the dead block has a predecessor whose branch has
+    // a configuration value that *could* be modified to
+    // silence the warning.
+    CFGBlock::const_pred_iterator PI = B->pred_begin();
+    if (PI != B->pred_end()) {
+      if (const CFGBlock *PredBlock = PI->getPossiblyUnreachableBlock()) {
+        const Stmt *TermCond =
+            PredBlock->getTerminatorCondition(/* strip parens */ false);
+        isConfigurationValue(TermCond, PP, &SilenceableCondVal);
+      }
+    }
+  }
+
   SourceRange R1, R2;
   SourceLocation Loc = GetUnreachableLoc(S, R1, R2);
-  CB.HandleUnreachable(Loc, R1, R2);
+  CB.HandleUnreachable(UK, Loc, SilenceableCondVal, R1, R2);
 }
 
+//===----------------------------------------------------------------------===//
+// Reachability APIs.
+//===----------------------------------------------------------------------===//
+
 namespace clang { namespace reachable_code {
 
-void Callback::anchor() { }  
+void Callback::anchor() { }
 
 unsigned ScanReachableFromBlock(const CFGBlock *Start,
                                 llvm::BitVector &Reachable) {
-  unsigned count = 0;
-  
-  // Prep work queue
-  SmallVector<const CFGBlock*, 32> WL;
-  
-  // The entry block may have already been marked reachable
-  // by the caller.
-  if (!Reachable[Start->getBlockID()]) {
-    ++count;
-    Reachable[Start->getBlockID()] = true;
-  }
-  
-  WL.push_back(Start);
-  
-  // Find the reachable blocks from 'Start'.
-  while (!WL.empty()) {
-    const CFGBlock *item = WL.pop_back_val();
-    
-    // Look at the successors and mark then reachable.
-    for (CFGBlock::const_succ_iterator I = item->succ_begin(), 
-         E = item->succ_end(); I != E; ++I)
-      if (const CFGBlock *B = *I) {
-        unsigned blockID = B->getBlockID();
-        if (!Reachable[blockID]) {
-          Reachable.set(blockID);
-          WL.push_back(B);
-          ++count;
-        }
-      }
-  }
-  return count;
+  return scanFromBlock(Start, Reachable, /* SourceManager* */ 0, false);
 }
-  
-void FindUnreachableCode(AnalysisDeclContext &AC, Callback &CB) {
+
+void FindUnreachableCode(AnalysisDeclContext &AC, Preprocessor &PP,
+                         Callback &CB) {
+
   CFG *cfg = AC.getCFG();
   if (!cfg)
     return;
 
-  // Scan for reachable blocks from the entrance of the CFG.  
+  // Scan for reachable blocks from the entrance of the CFG.
   // If there are no unreachable blocks, we're done.
   llvm::BitVector reachable(cfg->getNumBlockIDs());
-  unsigned numReachable = ScanReachableFromBlock(&cfg->getEntry(), reachable);
+  unsigned numReachable =
+    scanMaybeReachableFromBlock(&cfg->getEntry(), PP, reachable);
   if (numReachable == cfg->getNumBlockIDs())
     return;
   
@@ -309,7 +626,7 @@
   if (!AC.getCFGBuildOptions().AddEHEdges) {
     for (CFG::try_block_iterator I = cfg->try_blocks_begin(),
          E = cfg->try_blocks_end() ; I != E; ++I) {
-      numReachable += ScanReachableFromBlock(*I, reachable);
+      numReachable += scanMaybeReachableFromBlock(*I, PP, reachable);
     }
     if (numReachable == cfg->getNumBlockIDs())
       return;
@@ -323,7 +640,7 @@
     if (reachable[block->getBlockID()])
       continue;
     
-    DeadCodeScan DS(reachable);
+    DeadCodeScan DS(reachable, PP);
     numReachable += DS.scanBackwards(block, CB);
     
     if (numReachable == cfg->getNumBlockIDs())
diff --git a/lib/Analysis/ScanfFormatString.cpp b/lib/Analysis/ScanfFormatString.cpp
index f5ce84f..3ff7f0a 100644
--- a/lib/Analysis/ScanfFormatString.cpp
+++ b/lib/Analysis/ScanfFormatString.cpp
@@ -379,21 +379,23 @@
   return ArgType();
 }
 
-bool ScanfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
+bool ScanfSpecifier::fixType(QualType QT, QualType RawQT,
+                             const LangOptions &LangOpt,
                              ASTContext &Ctx) {
-  if (!QT->isPointerType())
-    return false;
 
   // %n is different from other conversion specifiers; don't try to fix it.
   if (CS.getKind() == ConversionSpecifier::nArg)
     return false;
 
+  if (!QT->isPointerType())
+    return false;
+
   QualType PT = QT->getPointeeType();
 
   // If it's an enum, get its underlying type.
-  if (const EnumType *ETy = QT->getAs<EnumType>())
-    QT = ETy->getDecl()->getIntegerType();
-  
+  if (const EnumType *ETy = PT->getAs<EnumType>())
+    PT = ETy->getDecl()->getIntegerType();
+
   const BuiltinType *BT = PT->getAs<BuiltinType>();
   if (!BT)
     return false;
@@ -405,6 +407,15 @@
       LM.setKind(LengthModifier::AsWideChar);
     else
       LM.setKind(LengthModifier::None);
+
+    // If we know the target array length, we can use it as a field width.
+    if (const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(RawQT)) {
+      if (CAT->getSizeModifier() == ArrayType::Normal)
+        FieldWidth = OptionalAmount(OptionalAmount::Constant,
+                                    CAT->getSize().getZExtValue() - 1,
+                                    "", 0, false);
+
+    }
     return true;
   }
 
diff --git a/lib/Analysis/ThreadSafety.cpp b/lib/Analysis/ThreadSafety.cpp
index 6e0e173..fd804eb 100644
--- a/lib/Analysis/ThreadSafety.cpp
+++ b/lib/Analysis/ThreadSafety.cpp
@@ -172,12 +172,9 @@
     const Expr* const* FunArgs;    // Function arguments
     CallingContext*    PrevCtx;    // The previous context; or 0 if none.
 
-    CallingContext(const NamedDecl *D = 0, const Expr *S = 0,
-                   unsigned N = 0, const Expr* const *A = 0,
-                   CallingContext *P = 0)
-      : AttrDecl(D), SelfArg(S), SelfArrow(false),
-        NumArgs(N), FunArgs(A), PrevCtx(P)
-    { }
+    CallingContext(const NamedDecl *D)
+        : AttrDecl(D), SelfArg(0), SelfArrow(false), NumArgs(0), FunArgs(0),
+          PrevCtx(0) {}
   };
 
   typedef SmallVector<SExprNode, 4> NodeVector;
@@ -188,44 +185,41 @@
   NodeVector NodeVec;
 
 private:
+  unsigned make(ExprOp O, unsigned F = 0, const void *D = 0) {
+    NodeVec.push_back(SExprNode(O, F, D));
+    return NodeVec.size() - 1;
+  }
+
   unsigned makeNop() {
-    NodeVec.push_back(SExprNode(EOP_Nop, 0, 0));
-    return NodeVec.size()-1;
+    return make(EOP_Nop);
   }
 
   unsigned makeWildcard() {
-    NodeVec.push_back(SExprNode(EOP_Wildcard, 0, 0));
-    return NodeVec.size()-1;
+    return make(EOP_Wildcard);
   }
 
   unsigned makeUniversal() {
-    NodeVec.push_back(SExprNode(EOP_Universal, 0, 0));
-    return NodeVec.size()-1;
+    return make(EOP_Universal);
   }
 
   unsigned makeNamedVar(const NamedDecl *D) {
-    NodeVec.push_back(SExprNode(EOP_NVar, 0, D));
-    return NodeVec.size()-1;
+    return make(EOP_NVar, 0, D);
   }
 
   unsigned makeLocalVar(const NamedDecl *D) {
-    NodeVec.push_back(SExprNode(EOP_LVar, 0, D));
-    return NodeVec.size()-1;
+    return make(EOP_LVar, 0, D);
   }
 
   unsigned makeThis() {
-    NodeVec.push_back(SExprNode(EOP_This, 0, 0));
-    return NodeVec.size()-1;
+    return make(EOP_This);
   }
 
   unsigned makeDot(const NamedDecl *D, bool Arrow) {
-    NodeVec.push_back(SExprNode(EOP_Dot, Arrow ? 1 : 0, D));
-    return NodeVec.size()-1;
+    return make(EOP_Dot, Arrow ? 1 : 0, D);
   }
 
   unsigned makeCall(unsigned NumArgs, const NamedDecl *D) {
-    NodeVec.push_back(SExprNode(EOP_Call, NumArgs, D));
-    return NodeVec.size()-1;
+    return make(EOP_Call, NumArgs, D);
   }
 
   // Grab the very first declaration of virtual method D
@@ -242,28 +236,23 @@
   }
 
   unsigned makeMCall(unsigned NumArgs, const CXXMethodDecl *D) {
-    NodeVec.push_back(SExprNode(EOP_MCall, NumArgs, getFirstVirtualDecl(D)));
-    return NodeVec.size()-1;
+    return make(EOP_MCall, NumArgs, getFirstVirtualDecl(D));
   }
 
   unsigned makeIndex() {
-    NodeVec.push_back(SExprNode(EOP_Index, 0, 0));
-    return NodeVec.size()-1;
+    return make(EOP_Index);
   }
 
   unsigned makeUnary() {
-    NodeVec.push_back(SExprNode(EOP_Unary, 0, 0));
-    return NodeVec.size()-1;
+    return make(EOP_Unary);
   }
 
   unsigned makeBinary() {
-    NodeVec.push_back(SExprNode(EOP_Binary, 0, 0));
-    return NodeVec.size()-1;
+    return make(EOP_Binary);
   }
 
   unsigned makeUnknown(unsigned Arity) {
-    NodeVec.push_back(SExprNode(EOP_Unknown, Arity, 0));
-    return NodeVec.size()-1;
+    return make(EOP_Unknown, Arity);
   }
 
   inline bool isCalleeArrow(const Expr *E) {
@@ -277,7 +266,7 @@
   /// ensure that the original expression is a valid mutex expression.
   ///
   /// NDeref returns the number of Derefence and AddressOf operations
-  /// preceeding the Expr; this is used to decide whether to pretty-print
+  /// preceding the Expr; this is used to decide whether to pretty-print
   /// SExprs with . or ->.
   unsigned buildSExpr(const Expr *Exp, CallingContext* CallCtx,
                       int* NDeref = 0) {
@@ -575,15 +564,15 @@
 
   /// Issue a warning about an invalid lock expression
   static void warnInvalidLock(ThreadSafetyHandler &Handler,
-                              const Expr *MutexExp,
-                              const Expr *DeclExp, const NamedDecl* D) {
+                              const Expr *MutexExp, const Expr *DeclExp,
+                              const NamedDecl *D, StringRef Kind) {
     SourceLocation Loc;
     if (DeclExp)
       Loc = DeclExp->getExprLoc();
 
     // FIXME: add a note about the attribute location in MutexExp or D
     if (Loc.isValid())
-      Handler.handleInvalidLockExp(Loc);
+      Handler.handleInvalidLockExp(Kind, Loc);
   }
 
   bool operator==(const SExpr &other) const {
@@ -716,27 +705,16 @@
   }
 };
 
-
-
 /// \brief A short list of SExprs
 class MutexIDList : public SmallVector<SExpr, 3> {
 public:
-  /// \brief Return true if the list contains the specified SExpr
-  /// Performs a linear search, because these lists are almost always very small.
-  bool contains(const SExpr& M) {
-    for (iterator I=begin(),E=end(); I != E; ++I)
-      if ((*I) == M) return true;
-    return false;
-  }
-
-  /// \brief Push M onto list, bud discard duplicates
+  /// \brief Push M onto list, but discard duplicates.
   void push_back_nodup(const SExpr& M) {
-    if (!contains(M)) push_back(M);
+    if (end() == std::find(begin(), end(), M))
+      push_back(M);
   }
 };
 
-
-
 /// \brief This is a helper class that stores info about the most recent
 /// accquire of a Lock.
 ///
@@ -1450,9 +1428,10 @@
 public:
   ThreadSafetyAnalyzer(ThreadSafetyHandler &H) : Handler(H) {}
 
-  void addLock(FactSet &FSet, const SExpr &Mutex, const LockData &LDat);
-  void removeLock(FactSet &FSet, const SExpr &Mutex,
-                  SourceLocation UnlockLoc, bool FullyRemove=false);
+  void addLock(FactSet &FSet, const SExpr &Mutex, const LockData &LDat,
+               StringRef DiagKind);
+  void removeLock(FactSet &FSet, const SExpr &Mutex, SourceLocation UnlockLoc,
+                  bool FullyRemove, LockKind Kind, StringRef DiagKind);
 
   template <typename AttrType>
   void getMutexIDs(MutexIDList &Mtxs, AttrType *Attr, Expr *Exp,
@@ -1485,12 +1464,89 @@
   void runAnalysis(AnalysisDeclContext &AC);
 };
 
+/// \brief Gets the value decl pointer from DeclRefExprs or MemberExprs.
+static const ValueDecl *getValueDecl(const Expr *Exp) {
+  if (const auto *CE = dyn_cast<ImplicitCastExpr>(Exp))
+    return getValueDecl(CE->getSubExpr());
+
+  if (const auto *DR = dyn_cast<DeclRefExpr>(Exp))
+    return DR->getDecl();
+
+  if (const auto *ME = dyn_cast<MemberExpr>(Exp))
+    return ME->getMemberDecl();
+
+  return nullptr;
+}
+
+template <typename Ty>
+class has_arg_iterator {
+  typedef char yes[1];
+  typedef char no[2];
+
+  template <typename Inner>
+  static yes& test(Inner *I, decltype(I->args_begin()) * = nullptr);
+
+  template <typename>
+  static no& test(...);
+
+public:
+  static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes);
+};
+
+static StringRef ClassifyDiagnostic(const CapabilityAttr *A) {
+  return A->getName();
+}
+
+static StringRef ClassifyDiagnostic(QualType VDT) {
+  // We need to look at the declaration of the type of the value to determine
+  // which it is. The type should either be a record or a typedef, or a pointer
+  // or reference thereof.
+  if (const auto *RT = VDT->getAs<RecordType>()) {
+    if (const auto *RD = RT->getDecl())
+      if (const auto *CA = RD->getAttr<CapabilityAttr>())
+        return ClassifyDiagnostic(CA);
+  } else if (const auto *TT = VDT->getAs<TypedefType>()) {
+    if (const auto *TD = TT->getDecl())
+      if (const auto *CA = TD->getAttr<CapabilityAttr>())
+        return ClassifyDiagnostic(CA);
+  } else if (VDT->isPointerType() || VDT->isReferenceType())
+    return ClassifyDiagnostic(VDT->getPointeeType());
+
+  return "mutex";
+}
+
+static StringRef ClassifyDiagnostic(const ValueDecl *VD) {
+  assert(VD && "No ValueDecl passed");
+
+  // The ValueDecl is the declaration of a mutex or role (hopefully).
+  return ClassifyDiagnostic(VD->getType());
+}
+
+template <typename AttrTy>
+static typename std::enable_if<!has_arg_iterator<AttrTy>::value,
+                               StringRef>::type
+ClassifyDiagnostic(const AttrTy *A) {
+  if (const ValueDecl *VD = getValueDecl(A->getArg()))
+    return ClassifyDiagnostic(VD);
+  return "mutex";
+}
+
+template <typename AttrTy>
+static typename std::enable_if<has_arg_iterator<AttrTy>::value,
+                               StringRef>::type
+ClassifyDiagnostic(const AttrTy *A) {
+  for (auto I = A->args_begin(), E = A->args_end(); I != E; ++I) {
+    if (const ValueDecl *VD = getValueDecl(*I))
+      return ClassifyDiagnostic(VD);
+  }
+  return "mutex";
+}
 
 /// \brief Add a new lock to the lockset, warning if the lock is already there.
 /// \param Mutex -- the Mutex expression for the lock
 /// \param LDat  -- the LockData for the lock
 void ThreadSafetyAnalyzer::addLock(FactSet &FSet, const SExpr &Mutex,
-                                   const LockData &LDat) {
+                                   const LockData &LDat, StringRef DiagKind) {
   // FIXME: deal with acquired before/after annotations.
   // FIXME: Don't always warn when we have support for reentrant locks.
   if (Mutex.shouldIgnore())
@@ -1498,7 +1554,7 @@
 
   if (FSet.findLock(FactMan, Mutex)) {
     if (!LDat.Asserted)
-      Handler.handleDoubleLock(Mutex.toString(), LDat.AcquireLoc);
+      Handler.handleDoubleLock(DiagKind, Mutex.toString(), LDat.AcquireLoc);
   } else {
     FSet.addLock(FactMan, Mutex, LDat);
   }
@@ -1508,16 +1564,24 @@
 /// \brief Remove a lock from the lockset, warning if the lock is not there.
 /// \param Mutex The lock expression corresponding to the lock to be removed
 /// \param UnlockLoc The source location of the unlock (only used in error msg)
-void ThreadSafetyAnalyzer::removeLock(FactSet &FSet,
-                                      const SExpr &Mutex,
+void ThreadSafetyAnalyzer::removeLock(FactSet &FSet, const SExpr &Mutex,
                                       SourceLocation UnlockLoc,
-                                      bool FullyRemove) {
+                                      bool FullyRemove, LockKind ReceivedKind,
+                                      StringRef DiagKind) {
   if (Mutex.shouldIgnore())
     return;
 
   const LockData *LDat = FSet.findLock(FactMan, Mutex);
   if (!LDat) {
-    Handler.handleUnmatchedUnlock(Mutex.toString(), UnlockLoc);
+    Handler.handleUnmatchedUnlock(DiagKind, Mutex.toString(), UnlockLoc);
+    return;
+  }
+
+  // Generic lock removal doesn't care about lock kind mismatches, but
+  // otherwise diagnose when the lock kinds are mismatched.
+  if (ReceivedKind != LK_Generic && LDat->LKind != ReceivedKind) {
+    Handler.handleIncorrectUnlockKind(DiagKind, Mutex.toString(), LDat->LKind,
+                                      ReceivedKind, UnlockLoc);
     return;
   }
 
@@ -1532,8 +1596,8 @@
       // We're releasing the underlying mutex, but not destroying the
       // managing object.  Warn on dual release.
       if (!FSet.findLock(FactMan, LDat->UnderlyingMutex)) {
-        Handler.handleUnmatchedUnlock(LDat->UnderlyingMutex.toString(),
-                                      UnlockLoc);
+        Handler.handleUnmatchedUnlock(
+            DiagKind, LDat->UnderlyingMutex.toString(), UnlockLoc);
       }
       FSet.removeLock(FactMan, LDat->UnderlyingMutex);
       return;
@@ -1555,7 +1619,7 @@
     // The mutex held is the "this" object.
     SExpr Mu(0, Exp, D, SelfDecl);
     if (!Mu.isValid())
-      SExpr::warnInvalidLock(Handler, 0, Exp, D);
+      SExpr::warnInvalidLock(Handler, 0, Exp, D, ClassifyDiagnostic(Attr));
     else
       Mtxs.push_back_nodup(Mu);
     return;
@@ -1564,7 +1628,7 @@
   for (iterator_type I=Attr->args_begin(), E=Attr->args_end(); I != E; ++I) {
     SExpr Mu(*I, Exp, D, SelfDecl);
     if (!Mu.isValid())
-      SExpr::warnInvalidLock(Handler, *I, Exp, D);
+      SExpr::warnInvalidLock(Handler, *I, Exp, D, ClassifyDiagnostic(Attr));
     else
       Mtxs.push_back_nodup(Mu);
   }
@@ -1697,6 +1761,7 @@
   bool Negate = false;
   const CFGBlockInfo *PredBlockInfo = &BlockInfo[PredBlock->getBlockID()];
   const LocalVarContext &LVarCtx = PredBlockInfo->ExitContext;
+  StringRef CapDiagKind = "mutex";
 
   CallExpr *Exp =
     const_cast<CallExpr*>(getTrylockCallExpr(Cond, LVarCtx, Negate));
@@ -1720,6 +1785,7 @@
           cast<ExclusiveTrylockFunctionAttr>(Attr);
         getMutexIDs(ExclusiveLocksToAdd, A, Exp, FunDecl,
                     PredBlock, CurrBlock, A->getSuccessValue(), Negate);
+        CapDiagKind = ClassifyDiagnostic(A);
         break;
       }
       case attr::SharedTrylockFunction: {
@@ -1727,6 +1793,7 @@
           cast<SharedTrylockFunctionAttr>(Attr);
         getMutexIDs(SharedLocksToAdd, A, Exp, FunDecl,
                     PredBlock, CurrBlock, A->getSuccessValue(), Negate);
+        CapDiagKind = ClassifyDiagnostic(A);
         break;
       }
       default:
@@ -1736,17 +1803,13 @@
 
   // Add and remove locks.
   SourceLocation Loc = Exp->getExprLoc();
-  for (unsigned i=0,n=ExclusiveLocksToAdd.size(); i<n; ++i) {
-    addLock(Result, ExclusiveLocksToAdd[i],
-            LockData(Loc, LK_Exclusive));
-  }
-  for (unsigned i=0,n=SharedLocksToAdd.size(); i<n; ++i) {
-    addLock(Result, SharedLocksToAdd[i],
-            LockData(Loc, LK_Shared));
-  }
+  for (const auto &ExclusiveLockToAdd : ExclusiveLocksToAdd)
+    addLock(Result, ExclusiveLockToAdd, LockData(Loc, LK_Exclusive),
+            CapDiagKind);
+  for (const auto &SharedLockToAdd : SharedLocksToAdd)
+    addLock(Result, SharedLockToAdd, LockData(Loc, LK_Shared), CapDiagKind);
 }
 
-
 /// \brief We use this class to visit different types of expressions in
 /// CFGBlocks, and build up the lockset.
 /// An expression may cause us to add or remove locks from the lockset, or else
@@ -1761,11 +1824,12 @@
   unsigned CtxIndex;
 
   // Helper functions
-  const ValueDecl *getValueDecl(const Expr *Exp);
 
   void warnIfMutexNotHeld(const NamedDecl *D, const Expr *Exp, AccessKind AK,
-                          Expr *MutexExp, ProtectedOperationKind POK);
-  void warnIfMutexHeld(const NamedDecl *D, const Expr *Exp, Expr *MutexExp);
+                          Expr *MutexExp, ProtectedOperationKind POK,
+                          StringRef DiagKind);
+  void warnIfMutexHeld(const NamedDecl *D, const Expr *Exp, Expr *MutexExp,
+                       StringRef DiagKind);
 
   void checkAccess(const Expr *Exp, AccessKind AK);
   void checkPtAccess(const Expr *Exp, AccessKind AK);
@@ -1789,31 +1853,17 @@
   void VisitDeclStmt(DeclStmt *S);
 };
 
-
-/// \brief Gets the value decl pointer from DeclRefExprs or MemberExprs
-const ValueDecl *BuildLockset::getValueDecl(const Expr *Exp) {
-  if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(Exp))
-    return getValueDecl(CE->getSubExpr());
-
-  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Exp))
-    return DR->getDecl();
-
-  if (const MemberExpr *ME = dyn_cast<MemberExpr>(Exp))
-    return ME->getMemberDecl();
-
-  return 0;
-}
-
 /// \brief Warn if the LSet does not contain a lock sufficient to protect access
 /// of at least the passed in AccessKind.
 void BuildLockset::warnIfMutexNotHeld(const NamedDecl *D, const Expr *Exp,
                                       AccessKind AK, Expr *MutexExp,
-                                      ProtectedOperationKind POK) {
+                                      ProtectedOperationKind POK,
+                                      StringRef DiagKind) {
   LockKind LK = getLockKindFromAccessKind(AK);
 
   SExpr Mutex(MutexExp, Exp, D);
   if (!Mutex.isValid()) {
-    SExpr::warnInvalidLock(Analyzer->Handler, MutexExp, Exp, D);
+    SExpr::warnInvalidLock(Analyzer->Handler, MutexExp, Exp, D, DiagKind);
     return;
   } else if (Mutex.shouldIgnore()) {
     return;
@@ -1829,40 +1879,38 @@
       LDat = &FEntry->LDat;
       std::string PartMatchStr = FEntry->MutID.toString();
       StringRef   PartMatchName(PartMatchStr);
-      Analyzer->Handler.handleMutexNotHeld(D, POK, Mutex.toString(), LK,
-                                           Exp->getExprLoc(), &PartMatchName);
+      Analyzer->Handler.handleMutexNotHeld(DiagKind, D, POK, Mutex.toString(),
+                                           LK, Exp->getExprLoc(),
+                                           &PartMatchName);
     } else {
       // Warn that there's no match at all.
-      Analyzer->Handler.handleMutexNotHeld(D, POK, Mutex.toString(), LK,
-                                           Exp->getExprLoc());
+      Analyzer->Handler.handleMutexNotHeld(DiagKind, D, POK, Mutex.toString(),
+                                           LK, Exp->getExprLoc());
     }
     NoError = false;
   }
   // Make sure the mutex we found is the right kind.
   if (NoError && LDat && !LDat->isAtLeast(LK))
-    Analyzer->Handler.handleMutexNotHeld(D, POK, Mutex.toString(), LK,
+    Analyzer->Handler.handleMutexNotHeld(DiagKind, D, POK, Mutex.toString(), LK,
                                          Exp->getExprLoc());
 }
 
 /// \brief Warn if the LSet contains the given lock.
-void BuildLockset::warnIfMutexHeld(const NamedDecl *D, const Expr* Exp,
-                                   Expr *MutexExp) {
+void BuildLockset::warnIfMutexHeld(const NamedDecl *D, const Expr *Exp,
+                                   Expr *MutexExp,
+                                   StringRef DiagKind) {
   SExpr Mutex(MutexExp, Exp, D);
   if (!Mutex.isValid()) {
-    SExpr::warnInvalidLock(Analyzer->Handler, MutexExp, Exp, D);
+    SExpr::warnInvalidLock(Analyzer->Handler, MutexExp, Exp, D, DiagKind);
     return;
   }
 
   LockData* LDat = FSet.findLock(Analyzer->FactMan, Mutex);
-  if (LDat) {
-    std::string DeclName = D->getNameAsString();
-    StringRef   DeclNameSR (DeclName);
-    Analyzer->Handler.handleFunExcludesLock(DeclNameSR, Mutex.toString(),
-                                            Exp->getExprLoc());
-  }
+  if (LDat)
+    Analyzer->Handler.handleFunExcludesLock(
+        DiagKind, D->getNameAsString(), Mutex.toString(), Exp->getExprLoc());
 }
 
-
 /// \brief Checks guarded_by and pt_guarded_by attributes.
 /// Whenever we identify an access (read or write) to a DeclRefExpr that is
 /// marked with guarded_by, we must ensure the appropriate mutexes are held.
@@ -1879,10 +1927,8 @@
   }
 
   if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(Exp)) {
-    if (Analyzer->Handler.issueBetaWarnings()) {
-      checkPtAccess(AE->getLHS(), AK);
-      return;
-    }
+    checkPtAccess(AE->getLHS(), AK);
+    return;
   }
 
   if (const MemberExpr *ME = dyn_cast<MemberExpr>(Exp)) {
@@ -1896,55 +1942,48 @@
   if (!D || !D->hasAttrs())
     return;
 
-  if (D->getAttr<GuardedVarAttr>() && FSet.isEmpty())
-    Analyzer->Handler.handleNoMutexHeld(D, POK_VarAccess, AK,
+  if (D->hasAttr<GuardedVarAttr>() && FSet.isEmpty())
+    Analyzer->Handler.handleNoMutexHeld("mutex", D, POK_VarAccess, AK,
                                         Exp->getExprLoc());
 
-  const AttrVec &ArgAttrs = D->getAttrs();
-  for (unsigned i = 0, Size = ArgAttrs.size(); i < Size; ++i)
-    if (GuardedByAttr *GBAttr = dyn_cast<GuardedByAttr>(ArgAttrs[i]))
-      warnIfMutexNotHeld(D, Exp, AK, GBAttr->getArg(), POK_VarAccess);
+  for (const auto *I : D->specific_attrs<GuardedByAttr>())
+    warnIfMutexNotHeld(D, Exp, AK, I->getArg(), POK_VarAccess,
+                       ClassifyDiagnostic(I));
 }
 
 /// \brief Checks pt_guarded_by and pt_guarded_var attributes.
 void BuildLockset::checkPtAccess(const Expr *Exp, AccessKind AK) {
-  if (Analyzer->Handler.issueBetaWarnings()) {
-    while (true) {
-      if (const ParenExpr *PE = dyn_cast<ParenExpr>(Exp)) {
-        Exp = PE->getSubExpr();
-        continue;
-      }
-      if (const CastExpr *CE = dyn_cast<CastExpr>(Exp)) {
-        if (CE->getCastKind() == CK_ArrayToPointerDecay) {
-          // If it's an actual array, and not a pointer, then it's elements
-          // are protected by GUARDED_BY, not PT_GUARDED_BY;
-          checkAccess(CE->getSubExpr(), AK);
-          return;
-        }
-        Exp = CE->getSubExpr();
-        continue;
-      }
-      break;
+  while (true) {
+    if (const ParenExpr *PE = dyn_cast<ParenExpr>(Exp)) {
+      Exp = PE->getSubExpr();
+      continue;
     }
+    if (const CastExpr *CE = dyn_cast<CastExpr>(Exp)) {
+      if (CE->getCastKind() == CK_ArrayToPointerDecay) {
+        // If it's an actual array, and not a pointer, then it's elements
+        // are protected by GUARDED_BY, not PT_GUARDED_BY;
+        checkAccess(CE->getSubExpr(), AK);
+        return;
+      }
+      Exp = CE->getSubExpr();
+      continue;
+    }
+    break;
   }
-  else
-    Exp = Exp->IgnoreParenCasts();
 
   const ValueDecl *D = getValueDecl(Exp);
   if (!D || !D->hasAttrs())
     return;
 
-  if (D->getAttr<PtGuardedVarAttr>() && FSet.isEmpty())
-    Analyzer->Handler.handleNoMutexHeld(D, POK_VarDereference, AK,
+  if (D->hasAttr<PtGuardedVarAttr>() && FSet.isEmpty())
+    Analyzer->Handler.handleNoMutexHeld("mutex", D, POK_VarDereference, AK,
                                         Exp->getExprLoc());
 
-  const AttrVec &ArgAttrs = D->getAttrs();
-  for (unsigned i = 0, Size = ArgAttrs.size(); i < Size; ++i)
-    if (PtGuardedByAttr *GBAttr = dyn_cast<PtGuardedByAttr>(ArgAttrs[i]))
-      warnIfMutexNotHeld(D, Exp, AK, GBAttr->getArg(), POK_VarDereference);
+  for (auto const *I : D->specific_attrs<PtGuardedByAttr>())
+    warnIfMutexNotHeld(D, Exp, AK, I->getArg(), POK_VarDereference,
+                       ClassifyDiagnostic(I));
 }
 
-
 /// \brief Process a function call, method call, constructor call,
 /// or destructor call.  This involves looking at the attributes on the
 /// corresponding function/method/constructor/destructor, issuing warnings,
@@ -1958,26 +1997,22 @@
 void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
   SourceLocation Loc = Exp->getExprLoc();
   const AttrVec &ArgAttrs = D->getAttrs();
-  MutexIDList ExclusiveLocksToAdd;
-  MutexIDList SharedLocksToAdd;
-  MutexIDList LocksToRemove;
+  MutexIDList ExclusiveLocksToAdd, SharedLocksToAdd;
+  MutexIDList ExclusiveLocksToRemove, SharedLocksToRemove, GenericLocksToRemove;
+  StringRef CapDiagKind = "mutex";
 
   for(unsigned i = 0; i < ArgAttrs.size(); ++i) {
     Attr *At = const_cast<Attr*>(ArgAttrs[i]);
     switch (At->getKind()) {
-      // When we encounter an exclusive lock function, we need to add the lock
-      // to our lockset with kind exclusive.
-      case attr::ExclusiveLockFunction: {
-        ExclusiveLockFunctionAttr *A = cast<ExclusiveLockFunctionAttr>(At);
-        Analyzer->getMutexIDs(ExclusiveLocksToAdd, A, Exp, D, VD);
-        break;
-      }
+      // When we encounter a lock function, we need to add the lock to our
+      // lockset.
+      case attr::AcquireCapability: {
+        auto *A = cast<AcquireCapabilityAttr>(At);
+        Analyzer->getMutexIDs(A->isShared() ? SharedLocksToAdd
+                                            : ExclusiveLocksToAdd,
+                              A, Exp, D, VD);
 
-      // When we encounter a shared lock function, we need to add the lock
-      // to our lockset with kind shared.
-      case attr::SharedLockFunction: {
-        SharedLockFunctionAttr *A = cast<SharedLockFunctionAttr>(At);
-        Analyzer->getMutexIDs(SharedLocksToAdd, A, Exp, D, VD);
+        CapDiagKind = ClassifyDiagnostic(A);
         break;
       }
 
@@ -1989,10 +2024,10 @@
 
         MutexIDList AssertLocks;
         Analyzer->getMutexIDs(AssertLocks, A, Exp, D, VD);
-        for (unsigned i=0,n=AssertLocks.size(); i<n; ++i) {
-          Analyzer->addLock(FSet, AssertLocks[i],
-                            LockData(Loc, LK_Exclusive, false, true));
-        }
+        for (const auto &AssertLock : AssertLocks)
+          Analyzer->addLock(FSet, AssertLock,
+                            LockData(Loc, LK_Exclusive, false, true),
+                            ClassifyDiagnostic(A));
         break;
       }
       case attr::AssertSharedLock: {
@@ -2000,36 +2035,35 @@
 
         MutexIDList AssertLocks;
         Analyzer->getMutexIDs(AssertLocks, A, Exp, D, VD);
-        for (unsigned i=0,n=AssertLocks.size(); i<n; ++i) {
-          Analyzer->addLock(FSet, AssertLocks[i],
-                            LockData(Loc, LK_Shared, false, true));
-        }
+        for (const auto &AssertLock : AssertLocks)
+          Analyzer->addLock(FSet, AssertLock,
+                            LockData(Loc, LK_Shared, false, true),
+                            ClassifyDiagnostic(A));
         break;
       }
 
       // When we encounter an unlock function, we need to remove unlocked
       // mutexes from the lockset, and flag a warning if they are not there.
-      case attr::UnlockFunction: {
-        UnlockFunctionAttr *A = cast<UnlockFunctionAttr>(At);
-        Analyzer->getMutexIDs(LocksToRemove, A, Exp, D, VD);
+      case attr::ReleaseCapability: {
+        auto *A = cast<ReleaseCapabilityAttr>(At);
+        if (A->isGeneric())
+          Analyzer->getMutexIDs(GenericLocksToRemove, A, Exp, D, VD);
+        else if (A->isShared())
+          Analyzer->getMutexIDs(SharedLocksToRemove, A, Exp, D, VD);
+        else
+          Analyzer->getMutexIDs(ExclusiveLocksToRemove, A, Exp, D, VD);
+
+        CapDiagKind = ClassifyDiagnostic(A);
         break;
       }
 
-      case attr::ExclusiveLocksRequired: {
-        ExclusiveLocksRequiredAttr *A = cast<ExclusiveLocksRequiredAttr>(At);
+      case attr::RequiresCapability: {
+        RequiresCapabilityAttr *A = cast<RequiresCapabilityAttr>(At);
 
-        for (ExclusiveLocksRequiredAttr::args_iterator
-             I = A->args_begin(), E = A->args_end(); I != E; ++I)
-          warnIfMutexNotHeld(D, Exp, AK_Written, *I, POK_FunctionCall);
-        break;
-      }
-
-      case attr::SharedLocksRequired: {
-        SharedLocksRequiredAttr *A = cast<SharedLocksRequiredAttr>(At);
-
-        for (SharedLocksRequiredAttr::args_iterator I = A->args_begin(),
+        for (RequiresCapabilityAttr::args_iterator I = A->args_begin(),
              E = A->args_end(); I != E; ++I)
-          warnIfMutexNotHeld(D, Exp, AK_Read, *I, POK_FunctionCall);
+          warnIfMutexNotHeld(D, Exp, A->isShared() ? AK_Read : AK_Written, *I,
+                             POK_FunctionCall, ClassifyDiagnostic(A));
         break;
       }
 
@@ -2038,12 +2072,12 @@
 
         for (LocksExcludedAttr::args_iterator I = A->args_begin(),
             E = A->args_end(); I != E; ++I) {
-          warnIfMutexHeld(D, Exp, *I);
+          warnIfMutexHeld(D, Exp, *I, ClassifyDiagnostic(A));
         }
         break;
       }
 
-      // Ignore other (non thread-safety) attributes
+      // Ignore attributes unrelated to thread-safety
       default:
         break;
     }
@@ -2054,20 +2088,18 @@
   if (VD) {
     if (const CXXConstructorDecl *CD = dyn_cast<const CXXConstructorDecl>(D)) {
       const CXXRecordDecl* PD = CD->getParent();
-      if (PD && PD->getAttr<ScopedLockableAttr>())
+      if (PD && PD->hasAttr<ScopedLockableAttr>())
         isScopedVar = true;
     }
   }
 
   // Add locks.
-  for (unsigned i=0,n=ExclusiveLocksToAdd.size(); i<n; ++i) {
-    Analyzer->addLock(FSet, ExclusiveLocksToAdd[i],
-                            LockData(Loc, LK_Exclusive, isScopedVar));
-  }
-  for (unsigned i=0,n=SharedLocksToAdd.size(); i<n; ++i) {
-    Analyzer->addLock(FSet, SharedLocksToAdd[i],
-                            LockData(Loc, LK_Shared, isScopedVar));
-  }
+  for (const auto &M : ExclusiveLocksToAdd)
+    Analyzer->addLock(FSet, M, LockData(Loc, LK_Exclusive, isScopedVar),
+                      CapDiagKind);
+  for (const auto &M : SharedLocksToAdd)
+    Analyzer->addLock(FSet, M, LockData(Loc, LK_Shared, isScopedVar),
+                      CapDiagKind);
 
   // Add the managing object as a dummy mutex, mapped to the underlying mutex.
   // FIXME -- this doesn't work if we acquire multiple locks.
@@ -2076,22 +2108,23 @@
     DeclRefExpr DRE(VD, false, VD->getType(), VK_LValue, VD->getLocation());
     SExpr SMutex(&DRE, 0, 0);
 
-    for (unsigned i=0,n=ExclusiveLocksToAdd.size(); i<n; ++i) {
-      Analyzer->addLock(FSet, SMutex, LockData(MLoc, LK_Exclusive,
-                                               ExclusiveLocksToAdd[i]));
-    }
-    for (unsigned i=0,n=SharedLocksToAdd.size(); i<n; ++i) {
-      Analyzer->addLock(FSet, SMutex, LockData(MLoc, LK_Shared,
-                                               SharedLocksToAdd[i]));
-    }
+    for (const auto &M : ExclusiveLocksToAdd)
+      Analyzer->addLock(FSet, SMutex, LockData(MLoc, LK_Exclusive, M),
+                        CapDiagKind);
+    for (const auto &M : SharedLocksToAdd)
+      Analyzer->addLock(FSet, SMutex, LockData(MLoc, LK_Shared, M),
+                        CapDiagKind);
   }
 
   // Remove locks.
   // FIXME -- should only fully remove if the attribute refers to 'this'.
   bool Dtor = isa<CXXDestructorDecl>(D);
-  for (unsigned i=0,n=LocksToRemove.size(); i<n; ++i) {
-    Analyzer->removeLock(FSet, LocksToRemove[i], Loc, Dtor);
-  }
+  for (const auto &M : ExclusiveLocksToRemove)
+    Analyzer->removeLock(FSet, M, Loc, Dtor, LK_Exclusive, CapDiagKind);
+  for (const auto &M : SharedLocksToRemove)
+    Analyzer->removeLock(FSet, M, Loc, Dtor, LK_Shared, CapDiagKind);
+  for (const auto &M : GenericLocksToRemove)
+    Analyzer->removeLock(FSet, M, Loc, Dtor, LK_Generic, CapDiagKind);
 }
 
 
@@ -2168,11 +2201,9 @@
       case OO_Star:
       case OO_Arrow:
       case OO_Subscript: {
-        if (Analyzer->Handler.issueBetaWarnings()) {
-          const Expr *Obj = OE->getArg(0);
-          checkAccess(Obj, AK_Read);
-          checkPtAccess(Obj, AK_Read);
-        }
+        const Expr *Obj = OE->getArg(0);
+        checkAccess(Obj, AK_Read);
+        checkPtAccess(Obj, AK_Read);
         break;
       }
       default: {
@@ -2254,9 +2285,8 @@
     if (I1 != FSet1.end()) {
       const LockData* LDat1 = &FactMan[*I1].LDat;
       if (LDat1->LKind != LDat2.LKind) {
-        Handler.handleExclusiveAndShared(FSet2Mutex.toString(),
-                                         LDat2.AcquireLoc,
-                                         LDat1->AcquireLoc);
+        Handler.handleExclusiveAndShared("mutex", FSet2Mutex.toString(),
+                                         LDat2.AcquireLoc, LDat1->AcquireLoc);
         if (Modify && LDat1->LKind != LK_Exclusive) {
           // Take the exclusive lock, which is the one in FSet2.
           *I1 = *I;
@@ -2272,15 +2302,14 @@
           // If this is a scoped lock that manages another mutex, and if the
           // underlying mutex is still held, then warn about the underlying
           // mutex.
-          Handler.handleMutexHeldEndOfScope(LDat2.UnderlyingMutex.toString(),
-                                            LDat2.AcquireLoc,
-                                            JoinLoc, LEK1);
+          Handler.handleMutexHeldEndOfScope("mutex",
+                                            LDat2.UnderlyingMutex.toString(),
+                                            LDat2.AcquireLoc, JoinLoc, LEK1);
         }
       }
       else if (!LDat2.Managed && !FSet2Mutex.isUniversal() && !LDat2.Asserted)
-        Handler.handleMutexHeldEndOfScope(FSet2Mutex.toString(),
-                                          LDat2.AcquireLoc,
-                                          JoinLoc, LEK1);
+        Handler.handleMutexHeldEndOfScope("mutex", FSet2Mutex.toString(),
+                                          LDat2.AcquireLoc, JoinLoc, LEK1);
     }
   }
 
@@ -2296,15 +2325,14 @@
           // If this is a scoped lock that manages another mutex, and if the
           // underlying mutex is still held, then warn about the underlying
           // mutex.
-          Handler.handleMutexHeldEndOfScope(LDat1.UnderlyingMutex.toString(),
-                                            LDat1.AcquireLoc,
-                                            JoinLoc, LEK1);
+          Handler.handleMutexHeldEndOfScope("mutex",
+                                            LDat1.UnderlyingMutex.toString(),
+                                            LDat1.AcquireLoc, JoinLoc, LEK1);
         }
       }
       else if (!LDat1.Managed && !FSet1Mutex.isUniversal() && !LDat1.Asserted)
-        Handler.handleMutexHeldEndOfScope(FSet1Mutex.toString(),
-                                          LDat1.AcquireLoc,
-                                          JoinLoc, LEK2);
+        Handler.handleMutexHeldEndOfScope("mutex", FSet1Mutex.toString(),
+                                          LDat1.AcquireLoc, JoinLoc, LEK2);
       if (Modify)
         FSet1.removeLock(FactMan, FSet1Mutex);
     }
@@ -2342,7 +2370,7 @@
 
   if (!D)
     return;  // Ignore anonymous functions for now.
-  if (D->getAttr<NoThreadSafetyAnalysisAttr>())
+  if (D->hasAttr<NoThreadSafetyAnalysisAttr>())
     return;
   // FIXME: Do something a bit more intelligent inside constructor and
   // destructor code.  Constructors and destructors must assume unique access
@@ -2385,18 +2413,17 @@
 
     MutexIDList ExclusiveLocksToAdd;
     MutexIDList SharedLocksToAdd;
+    StringRef CapDiagKind = "mutex";
 
     SourceLocation Loc = D->getLocation();
     for (unsigned i = 0; i < ArgAttrs.size(); ++i) {
       Attr *Attr = ArgAttrs[i];
       Loc = Attr->getLocation();
-      if (ExclusiveLocksRequiredAttr *A
-            = dyn_cast<ExclusiveLocksRequiredAttr>(Attr)) {
-        getMutexIDs(ExclusiveLocksToAdd, A, (Expr*) 0, D);
-      } else if (SharedLocksRequiredAttr *A
-                   = dyn_cast<SharedLocksRequiredAttr>(Attr)) {
-        getMutexIDs(SharedLocksToAdd, A, (Expr*) 0, D);
-      } else if (UnlockFunctionAttr *A = dyn_cast<UnlockFunctionAttr>(Attr)) {
+      if (RequiresCapabilityAttr *A = dyn_cast<RequiresCapabilityAttr>(Attr)) {
+        getMutexIDs(A->isShared() ? SharedLocksToAdd : ExclusiveLocksToAdd, A,
+                    0, D);
+        CapDiagKind = ClassifyDiagnostic(A);
+      } else if (auto *A = dyn_cast<ReleaseCapabilityAttr>(Attr)) {
         // UNLOCK_FUNCTION() is used to hide the underlying lock implementation.
         // We must ignore such methods.
         if (A->args_size() == 0)
@@ -2404,16 +2431,14 @@
         // FIXME -- deal with exclusive vs. shared unlock functions?
         getMutexIDs(ExclusiveLocksToAdd, A, (Expr*) 0, D);
         getMutexIDs(LocksReleased, A, (Expr*) 0, D);
-      } else if (ExclusiveLockFunctionAttr *A
-                   = dyn_cast<ExclusiveLockFunctionAttr>(Attr)) {
+        CapDiagKind = ClassifyDiagnostic(A);
+      } else if (auto *A = dyn_cast<AcquireCapabilityAttr>(Attr)) {
         if (A->args_size() == 0)
           return;
-        getMutexIDs(ExclusiveLocksAcquired, A, (Expr*) 0, D);
-      } else if (SharedLockFunctionAttr *A
-                   = dyn_cast<SharedLockFunctionAttr>(Attr)) {
-        if (A->args_size() == 0)
-          return;
-        getMutexIDs(SharedLocksAcquired, A, (Expr*) 0, D);
+        getMutexIDs(A->isShared() ? SharedLocksAcquired
+                                  : ExclusiveLocksAcquired,
+                    A, nullptr, D);
+        CapDiagKind = ClassifyDiagnostic(A);
       } else if (isa<ExclusiveTrylockFunctionAttr>(Attr)) {
         // Don't try to check trylock functions for now
         return;
@@ -2424,14 +2449,12 @@
     }
 
     // FIXME -- Loc can be wrong here.
-    for (unsigned i=0,n=ExclusiveLocksToAdd.size(); i<n; ++i) {
-      addLock(InitialLockset, ExclusiveLocksToAdd[i],
-              LockData(Loc, LK_Exclusive));
-    }
-    for (unsigned i=0,n=SharedLocksToAdd.size(); i<n; ++i) {
-      addLock(InitialLockset, SharedLocksToAdd[i],
-              LockData(Loc, LK_Shared));
-    }
+    for (const auto &ExclusiveLockToAdd : ExclusiveLocksToAdd)
+      addLock(InitialLockset, ExclusiveLockToAdd, LockData(Loc, LK_Exclusive),
+              CapDiagKind);
+    for (const auto &SharedLockToAdd : SharedLocksToAdd)
+      addLock(InitialLockset, SharedLockToAdd, LockData(Loc, LK_Shared),
+              CapDiagKind);
   }
 
   for (PostOrderCFGView::iterator I = SortedGraph->begin(),
diff --git a/lib/Analysis/UninitializedValues.cpp b/lib/Analysis/UninitializedValues.cpp
index 332c02c..29c17c3 100644
--- a/lib/Analysis/UninitializedValues.cpp
+++ b/lib/Analysis/UninitializedValues.cpp
@@ -373,9 +373,8 @@
 }
 
 void ClassifyRefs::VisitDeclStmt(DeclStmt *DS) {
-  for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
-       DI != DE; ++DI) {
-    VarDecl *VD = dyn_cast<VarDecl>(*DI);
+  for (auto *DI : DS->decls()) {
+    VarDecl *VD = dyn_cast<VarDecl>(DI);
     if (VD && isTrackedVar(VD))
       if (const DeclRefExpr *DRE = getSelfInitExpr(VD))
         Classification[DRE] = SelfInit;
@@ -535,6 +534,9 @@
       for (CFGBlock::const_pred_iterator I = B->pred_begin(), E = B->pred_end();
            I != E; ++I) {
         const CFGBlock *Pred = *I;
+        if (!Pred)
+          continue;
+        
         Value AtPredExit = vals.getValue(Pred, B, vd);
         if (AtPredExit == Initialized)
           // This block initializes the variable.
@@ -630,12 +632,11 @@
 
 void TransferFunctions::VisitBlockExpr(BlockExpr *be) {
   const BlockDecl *bd = be->getBlockDecl();
-  for (BlockDecl::capture_const_iterator i = bd->capture_begin(),
-        e = bd->capture_end() ; i != e; ++i) {
-    const VarDecl *vd = i->getVariable();
+  for (const auto &I : bd->captures()) {
+    const VarDecl *vd = I.getVariable();
     if (!isTrackedVar(vd))
       continue;
-    if (i->isByRef()) {
+    if (I.isByRef()) {
       vals[vd] = Initialized;
       continue;
     }
@@ -691,9 +692,8 @@
 }
 
 void TransferFunctions::VisitDeclStmt(DeclStmt *DS) {
-  for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
-       DI != DE; ++DI) {
-    VarDecl *VD = dyn_cast<VarDecl>(*DI);
+  for (auto *DI : DS->decls()) {
+    VarDecl *VD = dyn_cast<VarDecl>(DI);
     if (VD && isTrackedVar(VD)) {
       if (getSelfInitExpr(VD)) {
         // If the initializer consists solely of a reference to itself, we
@@ -751,6 +751,8 @@
   for (CFGBlock::const_pred_iterator I = block->pred_begin(),
        E = block->pred_end(); I != E; ++I) {
     const CFGBlock *pred = *I;
+    if (!pred)
+      continue;
     if (wasAnalyzed[pred->getBlockID()]) {
       vals.mergeIntoScratch(vals.getValueVector(pred), isFirst);
       isFirst = false;
@@ -787,8 +789,8 @@
   /// The current block to scribble use information.
   unsigned currentBlock;
 
-  virtual void handleUseOfUninitVariable(const VarDecl *vd,
-                                         const UninitUse &use) {
+  void handleUseOfUninitVariable(const VarDecl *vd,
+                                 const UninitUse &use) override {
     hadUse[currentBlock] = true;
     hadAnyUse = true;
   }
@@ -796,7 +798,7 @@
   /// Called when the uninitialized variable analysis detects the
   /// idiom 'int x = x'.  All other uses of 'x' within the initializer
   /// are handled by handleUseOfUninitVariable.
-  virtual void handleSelfInit(const VarDecl *vd) {
+  void handleSelfInit(const VarDecl *vd) override {
     hadUse[currentBlock] = true;
     hadAnyUse = true;
   }