[clang-tidy] Move a few more checks from misc to bugprone.

Summary:
clang_tidy/rename_check.py misc-assert-side-effect bugprone-assert-side-effect
clang_tidy/rename_check.py misc-bool-pointer-implicit-conversion bugprone-bool-pointer-implicit-conversion
clang_tidy/rename_check.py misc-fold-init-type bugprone-fold-init-type
clang_tidy/rename_check.py misc-forward-declaration-namespace bugprone-forward-declaration-namespace
clang_tidy/rename_check.py misc-inaccurate-erase bugprone-inaccurate-erase
clang_tidy/rename_check.py misc-move-forwarding-reference bugprone-move-forwarding-reference
clang_tidy/rename_check.py misc-multiple-statement-macro bugprone-multiple-statement-macro
clang_tidy/rename_check.py misc-use-after-move bugprone-use-after-move
clang_tidy/rename_check.py misc-virtual-near-miss bugprone-virtual-near-miss

Manually fixed a reference to UseAfterMoveCheck in the hicpp module.
Manually fixed header guards.

Reviewers: hokein

Reviewed By: hokein

Subscribers: nemanjai, mgorny, javed.absar, xazax.hun, kbarton, cfe-commits

Differential Revision: https://reviews.llvm.org/D40426

llvm-svn: 318950
diff --git a/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.h b/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.h
index 050780d..2f5a751 100644
--- a/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.h
+++ b/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.h
@@ -7,8 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_ARGUMENTCOMMENTCHECK_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_ARGUMENTCOMMENTCHECK_H
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_ARGUMENTCOMMENTCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_ARGUMENTCOMMENTCHECK_H
 
 #include "../ClangTidy.h"
 #include "llvm/Support/Regex.h"
@@ -52,4 +52,4 @@
 } // namespace tidy
 } // namespace clang
 
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_ARGUMENTCOMMENTCHECK_H
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_ARGUMENTCOMMENTCHECK_H
diff --git a/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp
new file mode 100644
index 0000000..244e755
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp
@@ -0,0 +1,127 @@
+//===--- AssertSideEffectCheck.cpp - clang-tidy ---------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AssertSideEffectCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include <algorithm>
+#include <string>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+namespace {
+
+AST_MATCHER_P(Expr, hasSideEffect, bool, CheckFunctionCalls) {
+  const Expr *E = &Node;
+
+  if (const auto *Op = dyn_cast<UnaryOperator>(E)) {
+    UnaryOperator::Opcode OC = Op->getOpcode();
+    return OC == UO_PostInc || OC == UO_PostDec || OC == UO_PreInc ||
+           OC == UO_PreDec;
+  }
+
+  if (const auto *Op = dyn_cast<BinaryOperator>(E)) {
+    return Op->isAssignmentOp();
+  }
+
+  if (const auto *OpCallExpr = dyn_cast<CXXOperatorCallExpr>(E)) {
+    OverloadedOperatorKind OpKind = OpCallExpr->getOperator();
+    return OpKind == OO_Equal || OpKind == OO_PlusEqual ||
+           OpKind == OO_MinusEqual || OpKind == OO_StarEqual ||
+           OpKind == OO_SlashEqual || OpKind == OO_AmpEqual ||
+           OpKind == OO_PipeEqual || OpKind == OO_CaretEqual ||
+           OpKind == OO_LessLessEqual || OpKind == OO_GreaterGreaterEqual ||
+           OpKind == OO_PlusPlus || OpKind == OO_MinusMinus ||
+           OpKind == OO_PercentEqual || OpKind == OO_New ||
+           OpKind == OO_Delete || OpKind == OO_Array_New ||
+           OpKind == OO_Array_Delete;
+  }
+
+  if (const auto *CExpr = dyn_cast<CallExpr>(E)) {
+    bool Result = CheckFunctionCalls;
+    if (const auto *FuncDecl = CExpr->getDirectCallee()) {
+      if (FuncDecl->getDeclName().isIdentifier() &&
+          FuncDecl->getName() == "__builtin_expect") // exceptions come here
+        Result = false;
+      else if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(FuncDecl))
+        Result &= !MethodDecl->isConst();
+    }
+    return Result;
+  }
+
+  return isa<CXXNewExpr>(E) || isa<CXXDeleteExpr>(E) || isa<CXXThrowExpr>(E);
+}
+
+} // namespace
+
+AssertSideEffectCheck::AssertSideEffectCheck(StringRef Name,
+                                             ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      CheckFunctionCalls(Options.get("CheckFunctionCalls", false)),
+      RawAssertList(Options.get("AssertMacros", "assert")) {
+  StringRef(RawAssertList).split(AssertMacros, ",", -1, false);
+}
+
+// The options are explained in AssertSideEffectCheck.h.
+void AssertSideEffectCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "CheckFunctionCalls", CheckFunctionCalls);
+  Options.store(Opts, "AssertMacros", RawAssertList);
+}
+
+void AssertSideEffectCheck::registerMatchers(MatchFinder *Finder) {
+  auto DescendantWithSideEffect =
+      hasDescendant(expr(hasSideEffect(CheckFunctionCalls)));
+  auto ConditionWithSideEffect = hasCondition(DescendantWithSideEffect);
+  Finder->addMatcher(
+      stmt(
+          anyOf(conditionalOperator(ConditionWithSideEffect),
+                ifStmt(ConditionWithSideEffect),
+                unaryOperator(hasOperatorName("!"),
+                              hasUnaryOperand(unaryOperator(
+                                  hasOperatorName("!"),
+                                  hasUnaryOperand(DescendantWithSideEffect))))))
+          .bind("condStmt"),
+      this);
+}
+
+void AssertSideEffectCheck::check(const MatchFinder::MatchResult &Result) {
+  const SourceManager &SM = *Result.SourceManager;
+  const LangOptions LangOpts = getLangOpts();
+  SourceLocation Loc = Result.Nodes.getNodeAs<Stmt>("condStmt")->getLocStart();
+
+  StringRef AssertMacroName;
+  while (Loc.isValid() && Loc.isMacroID()) {
+    StringRef MacroName = Lexer::getImmediateMacroName(Loc, SM, LangOpts);
+
+    // Check if this macro is an assert.
+    if (std::find(AssertMacros.begin(), AssertMacros.end(), MacroName) !=
+        AssertMacros.end()) {
+      AssertMacroName = MacroName;
+      break;
+    }
+    Loc = SM.getImmediateMacroCallerLoc(Loc);
+  }
+  if (AssertMacroName.empty())
+    return;
+
+  diag(Loc, "found %0() with side effect") << AssertMacroName;
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.h b/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.h
new file mode 100644
index 0000000..0f386c9
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.h
@@ -0,0 +1,52 @@
+//===--- AssertSideEffectCheck.h - clang-tidy -------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_ASSERTSIDEEFFECTCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_ASSERTSIDEEFFECTCHECK_H
+
+#include "../ClangTidy.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Finds `assert()` with side effect.
+///
+/// The condition of `assert()` is evaluated only in debug builds so a
+/// condition with side effect can cause different behavior in debug / release
+/// builds.
+///
+/// There are two options:
+///
+///   - `AssertMacros`: A comma-separated list of the names of assert macros to
+///     be checked.
+///   - `CheckFunctionCalls`: Whether to treat non-const member and non-member
+///     functions as they produce side effects. Disabled by default because it
+///     can increase the number of false positive warnings.
+class AssertSideEffectCheck : public ClangTidyCheck {
+public:
+  AssertSideEffectCheck(StringRef Name, ClangTidyContext *Context);
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  const bool CheckFunctionCalls;
+  const std::string RawAssertList;
+  SmallVector<StringRef, 5> AssertMacros;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_ASSERTSIDEEFFECTCHECK_H
diff --git a/clang-tools-extra/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp
new file mode 100644
index 0000000..ed2c2db
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp
@@ -0,0 +1,73 @@
+//===--- BoolPointerImplicitConversionCheck.cpp - clang-tidy --------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "BoolPointerImplicitConversionCheck.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+void BoolPointerImplicitConversionCheck::registerMatchers(MatchFinder *Finder) {
+  // Look for ifs that have an implicit bool* to bool conversion in the
+  // condition. Filter negations.
+  Finder->addMatcher(
+      ifStmt(hasCondition(findAll(implicitCastExpr(
+                 allOf(unless(hasParent(unaryOperator(hasOperatorName("!")))),
+                       hasSourceExpression(expr(
+                           hasType(pointerType(pointee(booleanType()))),
+                           ignoringParenImpCasts(declRefExpr().bind("expr")))),
+                       hasCastKind(CK_PointerToBoolean))))),
+             unless(isInTemplateInstantiation()))
+          .bind("if"),
+      this);
+}
+
+void BoolPointerImplicitConversionCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  auto *If = Result.Nodes.getNodeAs<IfStmt>("if");
+  auto *Var = Result.Nodes.getNodeAs<DeclRefExpr>("expr");
+
+  // Ignore macros.
+  if (Var->getLocStart().isMacroID())
+    return;
+
+  // Only allow variable accesses for now, no function calls or member exprs.
+  // Check that we don't dereference the variable anywhere within the if. This
+  // avoids false positives for checks of the pointer for nullptr before it is
+  // dereferenced. If there is a dereferencing operator on this variable don't
+  // emit a diagnostic. Also ignore array subscripts.
+  const Decl *D = Var->getDecl();
+  auto DeclRef = ignoringParenImpCasts(declRefExpr(to(equalsNode(D))));
+  if (!match(findAll(
+                 unaryOperator(hasOperatorName("*"), hasUnaryOperand(DeclRef))),
+             *If, *Result.Context)
+           .empty() ||
+      !match(findAll(arraySubscriptExpr(hasBase(DeclRef))), *If,
+             *Result.Context)
+           .empty() ||
+      // FIXME: We should still warn if the paremater is implicitly converted to
+      // bool.
+      !match(findAll(callExpr(hasAnyArgument(ignoringParenImpCasts(DeclRef)))),
+             *If, *Result.Context)
+           .empty() ||
+      !match(findAll(cxxDeleteExpr(has(ignoringParenImpCasts(expr(DeclRef))))),
+             *If, *Result.Context)
+           .empty())
+    return;
+
+  diag(Var->getLocStart(), "dubious check of 'bool *' against 'nullptr', did "
+                           "you mean to dereference it?")
+      << FixItHint::CreateInsertion(Var->getLocStart(), "*");
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.h b/clang-tools-extra/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.h
new file mode 100644
index 0000000..b3416a9
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.h
@@ -0,0 +1,42 @@
+//===--- BoolPointerImplicitConversionCheck.h - clang-tidy ------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_BOOLPOINTERIMPLICITCONVERSIONCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_BOOLPOINTERIMPLICITCONVERSIONCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Checks for conditions based on implicit conversion from a bool pointer to
+/// bool.
+///
+/// Example:
+///
+/// \code
+///   bool *p;
+///   if (p) {
+///     // Never used in a pointer-specific way.
+///   }
+/// \endcode
+class BoolPointerImplicitConversionCheck : public ClangTidyCheck {
+public:
+  BoolPointerImplicitConversionCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_BOOLPOINTERIMPLICITCONVERSIONCHECK_H
diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
index e96dc81..d17eb27 100644
--- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -11,13 +11,22 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 #include "ArgumentCommentCheck.h"
+#include "AssertSideEffectCheck.h"
+#include "BoolPointerImplicitConversionCheck.h"
 #include "CopyConstructorInitCheck.h"
 #include "DanglingHandleCheck.h"
+#include "FoldInitTypeCheck.h"
+#include "ForwardDeclarationNamespaceCheck.h"
+#include "InaccurateEraseCheck.h"
 #include "IntegerDivisionCheck.h"
 #include "MisplacedOperatorInStrlenInAllocCheck.h"
+#include "MoveForwardingReferenceCheck.h"
+#include "MultipleStatementMacroCheck.h"
 #include "StringConstructorCheck.h"
 #include "SuspiciousMemsetUsageCheck.h"
 #include "UndefinedMemoryManipulationCheck.h"
+#include "UseAfterMoveCheck.h"
+#include "VirtualNearMissCheck.h"
 
 namespace clang {
 namespace tidy {
@@ -28,20 +37,38 @@
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
     CheckFactories.registerCheck<ArgumentCommentCheck>(
         "bugprone-argument-comment");
+    CheckFactories.registerCheck<AssertSideEffectCheck>(
+        "bugprone-assert-side-effect");
+    CheckFactories.registerCheck<BoolPointerImplicitConversionCheck>(
+        "bugprone-bool-pointer-implicit-conversion");
     CheckFactories.registerCheck<CopyConstructorInitCheck>(
         "bugprone-copy-constructor-init");
     CheckFactories.registerCheck<DanglingHandleCheck>(
         "bugprone-dangling-handle");
+    CheckFactories.registerCheck<FoldInitTypeCheck>(
+        "bugprone-fold-init-type");
+    CheckFactories.registerCheck<ForwardDeclarationNamespaceCheck>(
+        "bugprone-forward-declaration-namespace");
+    CheckFactories.registerCheck<InaccurateEraseCheck>(
+        "bugprone-inaccurate-erase");
     CheckFactories.registerCheck<IntegerDivisionCheck>(
         "bugprone-integer-division");
     CheckFactories.registerCheck<MisplacedOperatorInStrlenInAllocCheck>(
         "bugprone-misplaced-operator-in-strlen-in-alloc");
+    CheckFactories.registerCheck<MoveForwardingReferenceCheck>(
+        "bugprone-move-forwarding-reference");
+    CheckFactories.registerCheck<MultipleStatementMacroCheck>(
+        "bugprone-multiple-statement-macro");
     CheckFactories.registerCheck<StringConstructorCheck>(
         "bugprone-string-constructor");
     CheckFactories.registerCheck<SuspiciousMemsetUsageCheck>(
         "bugprone-suspicious-memset-usage");
     CheckFactories.registerCheck<UndefinedMemoryManipulationCheck>(
         "bugprone-undefined-memory-manipulation");
+    CheckFactories.registerCheck<UseAfterMoveCheck>(
+        "bugprone-use-after-move");
+    CheckFactories.registerCheck<VirtualNearMissCheck>(
+        "bugprone-virtual-near-miss");
   }
 };
 
diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
index fe9b999..dab77bd 100644
--- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
@@ -2,14 +2,23 @@
 
 add_clang_library(clangTidyBugproneModule
   ArgumentCommentCheck.cpp
+  AssertSideEffectCheck.cpp
+  BoolPointerImplicitConversionCheck.cpp
   BugproneTidyModule.cpp
   CopyConstructorInitCheck.cpp
   DanglingHandleCheck.cpp
+  FoldInitTypeCheck.cpp
+  ForwardDeclarationNamespaceCheck.cpp
+  InaccurateEraseCheck.cpp
   IntegerDivisionCheck.cpp
   MisplacedOperatorInStrlenInAllocCheck.cpp
+  MoveForwardingReferenceCheck.cpp
+  MultipleStatementMacroCheck.cpp
   StringConstructorCheck.cpp
   SuspiciousMemsetUsageCheck.cpp
   UndefinedMemoryManipulationCheck.cpp
+  UseAfterMoveCheck.cpp
+  VirtualNearMissCheck.cpp
 
   LINK_LIBS
   clangAnalysis
diff --git a/clang-tools-extra/clang-tidy/bugprone/FoldInitTypeCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/FoldInitTypeCheck.cpp
new file mode 100644
index 0000000..6d7fd28
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/FoldInitTypeCheck.cpp
@@ -0,0 +1,140 @@
+//===--- FoldInitTypeCheck.cpp - clang-tidy--------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FoldInitTypeCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+void FoldInitTypeCheck::registerMatchers(MatchFinder *Finder) {
+  // We match functions of interest and bind the iterator and init value types.
+  // Note: Right now we check only builtin types.
+  const auto BuiltinTypeWithId = [](const char *ID) {
+    return hasCanonicalType(builtinType().bind(ID));
+  };
+  const auto IteratorWithValueType = [&BuiltinTypeWithId](const char *ID) {
+    return anyOf(
+        // Pointer types.
+        pointsTo(BuiltinTypeWithId(ID)),
+        // Iterator types.
+        recordType(hasDeclaration(has(typedefNameDecl(
+            hasName("value_type"), hasType(BuiltinTypeWithId(ID)))))));
+  };
+
+  const auto IteratorParam = parmVarDecl(
+      hasType(hasCanonicalType(IteratorWithValueType("IterValueType"))));
+  const auto Iterator2Param = parmVarDecl(
+      hasType(hasCanonicalType(IteratorWithValueType("Iter2ValueType"))));
+  const auto InitParam = parmVarDecl(hasType(BuiltinTypeWithId("InitType")));
+
+  // std::accumulate, std::reduce.
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(
+                   hasAnyName("::std::accumulate", "::std::reduce"),
+                   hasParameter(0, IteratorParam), hasParameter(2, InitParam))),
+               argumentCountIs(3))
+          .bind("Call"),
+      this);
+  // std::inner_product.
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(hasName("::std::inner_product"),
+                                   hasParameter(0, IteratorParam),
+                                   hasParameter(2, Iterator2Param),
+                                   hasParameter(3, InitParam))),
+               argumentCountIs(4))
+          .bind("Call"),
+      this);
+  // std::reduce with a policy.
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(hasName("::std::reduce"),
+                                   hasParameter(1, IteratorParam),
+                                   hasParameter(3, InitParam))),
+               argumentCountIs(4))
+          .bind("Call"),
+      this);
+  // std::inner_product with a policy.
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(hasName("::std::inner_product"),
+                                   hasParameter(1, IteratorParam),
+                                   hasParameter(3, Iterator2Param),
+                                   hasParameter(4, InitParam))),
+               argumentCountIs(5))
+          .bind("Call"),
+      this);
+}
+
+/// Returns true if ValueType is allowed to fold into InitType, i.e. if:
+///   static_cast<InitType>(ValueType{some_value})
+/// does not result in trucation.
+static bool isValidBuiltinFold(const BuiltinType &ValueType,
+                               const BuiltinType &InitType,
+                               const ASTContext &Context) {
+  const auto ValueTypeSize = Context.getTypeSize(&ValueType);
+  const auto InitTypeSize = Context.getTypeSize(&InitType);
+  // It's OK to fold a float into a float of bigger or equal size, but not OK to
+  // fold into an int.
+  if (ValueType.isFloatingPoint())
+    return InitType.isFloatingPoint() && InitTypeSize >= ValueTypeSize;
+  // It's OK to fold an int into:
+  //  - an int of the same size and signedness.
+  //  - a bigger int, regardless of signedness.
+  //  - FIXME: should it be a warning to fold into floating point?
+  if (ValueType.isInteger()) {
+    if (InitType.isInteger()) {
+      if (InitType.isSignedInteger() == ValueType.isSignedInteger())
+        return InitTypeSize >= ValueTypeSize;
+      return InitTypeSize > ValueTypeSize;
+    }
+    if (InitType.isFloatingPoint())
+      return InitTypeSize >= ValueTypeSize;
+  }
+  return false;
+}
+
+/// Prints a diagnostic if IterValueType doe snot fold into IterValueType (see
+// isValidBuiltinFold for details).
+void FoldInitTypeCheck::doCheck(const BuiltinType &IterValueType,
+                                const BuiltinType &InitType,
+                                const ASTContext &Context,
+                                const CallExpr &CallNode) {
+  if (!isValidBuiltinFold(IterValueType, InitType, Context)) {
+    diag(CallNode.getExprLoc(), "folding type %0 into type %1 might result in "
+                                "loss of precision")
+        << IterValueType.desugar() << InitType.desugar();
+  }
+}
+
+void FoldInitTypeCheck::check(const MatchFinder::MatchResult &Result) {
+  // Given the iterator and init value type retreived by the matchers,
+  // we check that the ::value_type of the iterator is compatible with
+  // the init value type.
+  const auto *InitType = Result.Nodes.getNodeAs<BuiltinType>("InitType");
+  const auto *IterValueType =
+      Result.Nodes.getNodeAs<BuiltinType>("IterValueType");
+  assert(InitType != nullptr);
+  assert(IterValueType != nullptr);
+
+  const auto *CallNode = Result.Nodes.getNodeAs<CallExpr>("Call");
+  assert(CallNode != nullptr);
+
+  doCheck(*IterValueType, *InitType, *Result.Context, *CallNode);
+
+  if (const auto *Iter2ValueType =
+          Result.Nodes.getNodeAs<BuiltinType>("Iter2ValueType"))
+    doCheck(*Iter2ValueType, *InitType, *Result.Context, *CallNode);
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/bugprone/FoldInitTypeCheck.h b/clang-tools-extra/clang-tidy/bugprone/FoldInitTypeCheck.h
new file mode 100644
index 0000000..e6170de0
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/FoldInitTypeCheck.h
@@ -0,0 +1,44 @@
+//===--- FoldInitTypeCheck.h - clang-tidy------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FOLD_INIT_TYPE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FOLD_INIT_TYPE_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Find and flag invalid initializer values in folds, e.g. std::accumulate.
+/// Example:
+/// \code
+///   auto v = {65536L * 65536 * 65536};
+///   std::accumulate(begin(v), end(v), 0 /* int type is too small */);
+/// \endcode
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-fold-init-type.html
+class FoldInitTypeCheck : public ClangTidyCheck {
+public:
+  FoldInitTypeCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  void doCheck(const BuiltinType &IterValueType, const BuiltinType &InitType,
+               const ASTContext &Context, const CallExpr &CallNode);
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FOLD_INIT_TYPE_H
diff --git a/clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp
new file mode 100644
index 0000000..9ea5b55
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp
@@ -0,0 +1,174 @@
+//===--- ForwardDeclarationNamespaceCheck.cpp - clang-tidy ------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ForwardDeclarationNamespaceCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include <stack>
+#include <string>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+void ForwardDeclarationNamespaceCheck::registerMatchers(MatchFinder *Finder) {
+  // Match all class declarations/definitions *EXCEPT*
+  // 1. implicit classes, e.g. `class A {};` has implicit `class A` inside `A`.
+  // 2. nested classes declared/defined inside another class.
+  // 3. template class declaration, template instantiation or
+  //    specialization (NOTE: extern specialization is filtered out by
+  //    `unless(hasAncestor(cxxRecordDecl()))`).
+  auto IsInSpecialization = hasAncestor(
+      decl(anyOf(cxxRecordDecl(isExplicitTemplateSpecialization()),
+                 functionDecl(isExplicitTemplateSpecialization()))));
+  Finder->addMatcher(
+      cxxRecordDecl(
+          hasParent(decl(anyOf(namespaceDecl(), translationUnitDecl()))),
+          unless(isImplicit()), unless(hasAncestor(cxxRecordDecl())),
+          unless(isInstantiated()), unless(IsInSpecialization),
+          unless(classTemplateSpecializationDecl()))
+          .bind("record_decl"),
+      this);
+
+  // Match all friend declarations. Classes used in friend declarations are not
+  // marked as referenced in AST. We need to record all record classes used in
+  // friend declarations.
+  Finder->addMatcher(friendDecl().bind("friend_decl"), this);
+}
+
+void ForwardDeclarationNamespaceCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  if (const auto *RecordDecl =
+          Result.Nodes.getNodeAs<CXXRecordDecl>("record_decl")) {
+    StringRef DeclName = RecordDecl->getName();
+    if (RecordDecl->isThisDeclarationADefinition()) {
+      DeclNameToDefinitions[DeclName].push_back(RecordDecl);
+    } else {
+      // If a declaration has no definition, the definition could be in another
+      // namespace (a wrong namespace).
+      // NOTE: even a declaration does have definition, we still need it to
+      // compare with other declarations.
+      DeclNameToDeclarations[DeclName].push_back(RecordDecl);
+    }
+  } else {
+    const auto *Decl = Result.Nodes.getNodeAs<FriendDecl>("friend_decl");
+    assert(Decl && "Decl is neither record_decl nor friend decl!");
+
+    // Classes used in friend delarations are not marked referenced in AST,
+    // so we need to check classes used in friend declarations manually to
+    // reduce the rate of false positive.
+    // For example, in
+    //    \code
+    //      struct A;
+    //      struct B { friend A; };
+    //    \endcode
+    // `A` will not be marked as "referenced" in the AST.
+    if (const TypeSourceInfo *Tsi = Decl->getFriendType()) {
+      QualType Desugared = Tsi->getType().getDesugaredType(*Result.Context);
+      FriendTypes.insert(Desugared.getTypePtr());
+    }
+  }
+}
+
+static bool haveSameNamespaceOrTranslationUnit(const CXXRecordDecl *Decl1,
+                                               const CXXRecordDecl *Decl2) {
+  const DeclContext *ParentDecl1 = Decl1->getLexicalParent();
+  const DeclContext *ParentDecl2 = Decl2->getLexicalParent();
+
+  // Since we only matched declarations whose parent is Namespace or
+  // TranslationUnit declaration, the parent should be either a translation unit
+  // or namespace.
+  if (ParentDecl1->getDeclKind() == Decl::TranslationUnit ||
+      ParentDecl2->getDeclKind() == Decl::TranslationUnit) {
+    return ParentDecl1 == ParentDecl2;
+  }
+  assert(ParentDecl1->getDeclKind() == Decl::Namespace &&
+         "ParentDecl1 declaration must be a namespace");
+  assert(ParentDecl2->getDeclKind() == Decl::Namespace &&
+         "ParentDecl2 declaration must be a namespace");
+  auto *Ns1 = NamespaceDecl::castFromDeclContext(ParentDecl1);
+  auto *Ns2 = NamespaceDecl::castFromDeclContext(ParentDecl2);
+  return Ns1->getOriginalNamespace() == Ns2->getOriginalNamespace();
+}
+
+static std::string getNameOfNamespace(const CXXRecordDecl *Decl) {
+  const auto *ParentDecl = Decl->getLexicalParent();
+  if (ParentDecl->getDeclKind() == Decl::TranslationUnit) {
+    return "(global)";
+  }
+  const auto *NsDecl = cast<NamespaceDecl>(ParentDecl);
+  std::string Ns;
+  llvm::raw_string_ostream OStream(Ns);
+  NsDecl->printQualifiedName(OStream);
+  OStream.flush();
+  return Ns.empty() ? "(global)" : Ns;
+}
+
+void ForwardDeclarationNamespaceCheck::onEndOfTranslationUnit() {
+  // Iterate each group of declarations by name.
+  for (const auto &KeyValuePair : DeclNameToDeclarations) {
+    const auto &Declarations = KeyValuePair.second;
+    // If more than 1 declaration exists, we check if all are in the same
+    // namespace.
+    for (const auto *CurDecl : Declarations) {
+      if (CurDecl->hasDefinition() || CurDecl->isReferenced()) {
+        continue; // Skip forward declarations that are used/referenced.
+      }
+      if (FriendTypes.count(CurDecl->getTypeForDecl()) != 0) {
+        continue; // Skip forward declarations referenced as friend.
+      }
+      if (CurDecl->getLocation().isMacroID() ||
+          CurDecl->getLocation().isInvalid()) {
+        continue;
+      }
+      // Compare with all other declarations with the same name.
+      for (const auto *Decl : Declarations) {
+        if (Decl == CurDecl) {
+          continue; // Don't compare with self.
+        }
+        if (!CurDecl->hasDefinition() &&
+            !haveSameNamespaceOrTranslationUnit(CurDecl, Decl)) {
+          diag(CurDecl->getLocation(),
+               "declaration %0 is never referenced, but a declaration with "
+               "the same name found in another namespace '%1'")
+              << CurDecl << getNameOfNamespace(Decl);
+          diag(Decl->getLocation(), "a declaration of %0 is found here",
+               DiagnosticIDs::Note)
+              << Decl;
+          break; // FIXME: We only generate one warning for each declaration.
+        }
+      }
+      // Check if a definition in another namespace exists.
+      const auto DeclName = CurDecl->getName();
+      if (DeclNameToDefinitions.find(DeclName) == DeclNameToDefinitions.end()) {
+        continue; // No definition in this translation unit, we can skip it.
+      }
+      // Make a warning for each definition with the same name (in other
+      // namespaces).
+      const auto &Definitions = DeclNameToDefinitions[DeclName];
+      for (const auto *Def : Definitions) {
+        diag(CurDecl->getLocation(),
+             "no definition found for %0, but a definition with "
+             "the same name %1 found in another namespace '%2'")
+            << CurDecl << Def << getNameOfNamespace(Def);
+        diag(Def->getLocation(), "a definition of %0 is found here",
+             DiagnosticIDs::Note)
+            << Def;
+      }
+    }
+  }
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.h b/clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.h
new file mode 100644
index 0000000..c3d3018
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.h
@@ -0,0 +1,59 @@
+//===--- ForwardDeclarationNamespaceCheck.h - clang-tidy --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FORWARDDECLARATIONNAMESPACECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FORWARDDECLARATIONNAMESPACECHECK_H
+
+#include "../ClangTidy.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include <set>
+#include <vector>
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Checks if an unused forward declaration is in a wrong namespace.
+///
+/// The check inspects all unused forward declarations and checks if there is
+/// any declaration/definition with the same name, which could indicate
+/// that the forward declaration is potentially in a wrong namespace.
+///
+/// \code
+///   namespace na { struct A; }
+///   namespace nb { struct A {} };
+///   nb::A a;
+///   // warning : no definition found for 'A', but a definition with the same
+///   name 'A' found in another namespace 'nb::'
+/// \endcode
+///
+/// This check can only generate warnings, but it can't suggest fixes at this
+/// point.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-forward-declaration-namespace.html
+class ForwardDeclarationNamespaceCheck : public ClangTidyCheck {
+public:
+  ForwardDeclarationNamespaceCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void onEndOfTranslationUnit() override;
+
+private:
+  llvm::StringMap<std::vector<const CXXRecordDecl *>> DeclNameToDefinitions;
+  llvm::StringMap<std::vector<const CXXRecordDecl *>> DeclNameToDeclarations;
+  llvm::SmallPtrSet<const Type *, 16> FriendTypes;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FORWARDDECLARATIONNAMESPACECHECK_H
diff --git a/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.cpp
new file mode 100644
index 0000000..cf1be0e
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.cpp
@@ -0,0 +1,81 @@
+//===--- InaccurateEraseCheck.cpp - clang-tidy-----------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InaccurateEraseCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+namespace {
+AST_MATCHER(Decl, isInStdNamespace) { return Node.isInStdNamespace(); }
+}
+
+void InaccurateEraseCheck::registerMatchers(MatchFinder *Finder) {
+  // Only register the matchers for C++; the functionality currently does not
+  // provide any benefit to other languages, despite being benign.
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  const auto EndCall =
+      callExpr(
+          callee(functionDecl(hasAnyName("remove", "remove_if", "unique"))),
+          hasArgument(
+              1,
+              anyOf(cxxConstructExpr(has(ignoringImplicit(
+                        cxxMemberCallExpr(callee(cxxMethodDecl(hasName("end"))))
+                            .bind("end")))),
+                    anything())))
+          .bind("alg");
+
+  const auto DeclInStd = type(hasUnqualifiedDesugaredType(
+      tagType(hasDeclaration(decl(isInStdNamespace())))));
+  Finder->addMatcher(
+      cxxMemberCallExpr(
+          on(anyOf(hasType(DeclInStd), hasType(pointsTo(DeclInStd)))),
+          callee(cxxMethodDecl(hasName("erase"))), argumentCountIs(1),
+          hasArgument(0, has(ignoringImplicit(
+                             anyOf(EndCall, has(ignoringImplicit(EndCall)))))),
+          unless(isInTemplateInstantiation()))
+          .bind("erase"),
+      this);
+}
+
+void InaccurateEraseCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MemberCall =
+      Result.Nodes.getNodeAs<CXXMemberCallExpr>("erase");
+  const auto *EndExpr =
+      Result.Nodes.getNodeAs<CXXMemberCallExpr>("end");
+  const SourceLocation Loc = MemberCall->getLocStart();
+
+  FixItHint Hint;
+
+  if (!Loc.isMacroID() && EndExpr) {
+    const auto *AlgCall = Result.Nodes.getNodeAs<CallExpr>("alg");
+    std::string ReplacementText = Lexer::getSourceText(
+        CharSourceRange::getTokenRange(EndExpr->getSourceRange()),
+        *Result.SourceManager, getLangOpts());
+    const SourceLocation EndLoc = Lexer::getLocForEndOfToken(
+        AlgCall->getLocEnd(), 0, *Result.SourceManager, getLangOpts());
+    Hint = FixItHint::CreateInsertion(EndLoc, ", " + ReplacementText);
+  }
+
+  diag(Loc, "this call will remove at most one item even when multiple items "
+            "should be removed")
+      << Hint;
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.h b/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.h
new file mode 100644
index 0000000..d6b3729
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.h
@@ -0,0 +1,38 @@
+//===--- InaccurateEraseCheck.h - clang-tidy---------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INACCURATEERASECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INACCURATEERASECHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Checks for inaccurate use of the `erase()` method.
+///
+/// Algorithms like `remove()` do not actually remove any element from the
+/// container but return an iterator to the first redundant element at the end
+/// of the container. These redundant elements must be removed using the
+/// `erase()` method. This check warns when not all of the elements will be
+/// removed due to using an inappropriate overload.
+class InaccurateEraseCheck : public ClangTidyCheck {
+public:
+  InaccurateEraseCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INACCURATEERASECHECK_H
diff --git a/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp
new file mode 100644
index 0000000..516ee19
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp
@@ -0,0 +1,133 @@
+//===--- MoveForwardingReferenceCheck.cpp - clang-tidy --------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MoveForwardingReferenceCheck.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <algorithm>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+static void replaceMoveWithForward(const UnresolvedLookupExpr *Callee,
+                                   const ParmVarDecl *ParmVar,
+                                   const TemplateTypeParmDecl *TypeParmDecl,
+                                   DiagnosticBuilder &Diag,
+                                   const ASTContext &Context) {
+  const SourceManager &SM = Context.getSourceManager();
+  const LangOptions &LangOpts = Context.getLangOpts();
+
+  CharSourceRange CallRange =
+      Lexer::makeFileCharRange(CharSourceRange::getTokenRange(
+                                   Callee->getLocStart(), Callee->getLocEnd()),
+                               SM, LangOpts);
+
+  if (CallRange.isValid()) {
+    const std::string TypeName =
+        TypeParmDecl->getIdentifier()
+            ? TypeParmDecl->getName().str()
+            : (llvm::Twine("decltype(") + ParmVar->getName() + ")").str();
+
+    const std::string ForwardName =
+        (llvm::Twine("forward<") + TypeName + ">").str();
+
+    // Create a replacement only if we see a "standard" way of calling
+    // std::move(). This will hopefully prevent erroneous replacements if the
+    // code does unusual things (e.g. create an alias for std::move() in
+    // another namespace).
+    NestedNameSpecifier *NNS = Callee->getQualifier();
+    if (!NNS) {
+      // Called as "move" (i.e. presumably the code had a "using std::move;").
+      // We still conservatively put a "std::" in front of the forward because
+      // we don't know whether the code also had a "using std::forward;".
+      Diag << FixItHint::CreateReplacement(CallRange, "std::" + ForwardName);
+    } else if (const NamespaceDecl *Namespace = NNS->getAsNamespace()) {
+      if (Namespace->getName() == "std") {
+        if (!NNS->getPrefix()) {
+          // Called as "std::move".
+          Diag << FixItHint::CreateReplacement(CallRange,
+                                               "std::" + ForwardName);
+        } else if (NNS->getPrefix()->getKind() == NestedNameSpecifier::Global) {
+          // Called as "::std::move".
+          Diag << FixItHint::CreateReplacement(CallRange,
+                                               "::std::" + ForwardName);
+        }
+      }
+    }
+  }
+}
+
+void MoveForwardingReferenceCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus11)
+    return;
+
+  // Matches a ParmVarDecl for a forwarding reference, i.e. a non-const rvalue
+  // reference of a function template parameter type.
+  auto ForwardingReferenceParmMatcher =
+      parmVarDecl(
+          hasType(qualType(rValueReferenceType(),
+                           references(templateTypeParmType(hasDeclaration(
+                               templateTypeParmDecl().bind("type-parm-decl")))),
+                           unless(references(qualType(isConstQualified()))))))
+          .bind("parm-var");
+
+  Finder->addMatcher(
+      callExpr(callee(unresolvedLookupExpr(
+                          hasAnyDeclaration(namedDecl(
+                              hasUnderlyingDecl(hasName("::std::move")))))
+                          .bind("lookup")),
+               argumentCountIs(1),
+               hasArgument(0, ignoringParenImpCasts(declRefExpr(
+                                  to(ForwardingReferenceParmMatcher)))))
+          .bind("call-move"),
+      this);
+}
+
+void MoveForwardingReferenceCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *CallMove = Result.Nodes.getNodeAs<CallExpr>("call-move");
+  const auto *UnresolvedLookup =
+      Result.Nodes.getNodeAs<UnresolvedLookupExpr>("lookup");
+  const auto *ParmVar = Result.Nodes.getNodeAs<ParmVarDecl>("parm-var");
+  const auto *TypeParmDecl =
+      Result.Nodes.getNodeAs<TemplateTypeParmDecl>("type-parm-decl");
+
+  // Get the FunctionDecl and FunctionTemplateDecl containing the function
+  // parameter.
+  const auto *FuncForParam = dyn_cast<FunctionDecl>(ParmVar->getDeclContext());
+  if (!FuncForParam)
+    return;
+  const FunctionTemplateDecl *FuncTemplate =
+      FuncForParam->getDescribedFunctionTemplate();
+  if (!FuncTemplate)
+    return;
+
+  // Check that the template type parameter belongs to the same function
+  // template as the function parameter of that type. (This implies that type
+  // deduction will happen on the type.)
+  const TemplateParameterList *Params = FuncTemplate->getTemplateParameters();
+  if (!std::count(Params->begin(), Params->end(), TypeParmDecl))
+    return;
+
+  auto Diag = diag(CallMove->getExprLoc(),
+                   "forwarding reference passed to std::move(), which may "
+                   "unexpectedly cause lvalues to be moved; use "
+                   "std::forward() instead");
+
+  replaceMoveWithForward(UnresolvedLookup, ParmVar, TypeParmDecl, Diag,
+                         *Result.Context);
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.h b/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.h
new file mode 100644
index 0000000..c61de75
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.h
@@ -0,0 +1,49 @@
+//===--- MoveForwardingReferenceCheck.h - clang-tidy ----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MOVEFORWARDINGREFERENCECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MOVEFORWARDINGREFERENCECHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// The check warns if std::move is applied to a forwarding reference (i.e. an
+/// rvalue reference of a function template argument type).
+///
+/// If a developer is unaware of the special rules for template argument
+/// deduction on forwarding references, it will seem reasonable to apply
+/// std::move to the forwarding reference, in the same way that this would be
+/// done for a "normal" rvalue reference.
+///
+/// This has a consequence that is usually unwanted and possibly surprising: if
+/// the function that takes the forwarding reference as its parameter is called
+/// with an lvalue, that lvalue will be moved from (and hence placed into an
+/// indeterminate state) even though no std::move was applied to the lvalue at
+/// the call site.
+//
+/// The check suggests replacing the std::move with a std::forward.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-move-forwarding-reference.html
+class MoveForwardingReferenceCheck : public ClangTidyCheck {
+public:
+  MoveForwardingReferenceCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MOVEFORWARDINGREFERENCECHECK_H
diff --git a/clang-tools-extra/clang-tidy/bugprone/MultipleStatementMacroCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/MultipleStatementMacroCheck.cpp
new file mode 100644
index 0000000..9fa2f43
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/MultipleStatementMacroCheck.cpp
@@ -0,0 +1,106 @@
+//===--- MultipleStatementMacroCheck.cpp - clang-tidy----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MultipleStatementMacroCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+namespace {
+
+AST_MATCHER(Expr, isInMacro) { return Node.getLocStart().isMacroID(); }
+
+/// \brief Find the next statement after `S`.
+const Stmt *nextStmt(const MatchFinder::MatchResult &Result, const Stmt *S) {
+  auto Parents = Result.Context->getParents(*S);
+  if (Parents.empty())
+    return nullptr;
+  const auto *Parent = Parents[0].get<Stmt>();
+  if (!Parent)
+    return nullptr;
+  const Stmt *Prev = nullptr;
+  for (const Stmt *Child : Parent->children()) {
+    if (Prev == S)
+      return Child;
+    Prev = Child;
+  }
+  return nextStmt(Result, Parent);
+}
+
+using ExpansionRanges = std::vector<std::pair<SourceLocation, SourceLocation>>;
+
+/// \bried Get all the macro expansion ranges related to `Loc`.
+///
+/// The result is ordered from most inner to most outer.
+ExpansionRanges getExpansionRanges(SourceLocation Loc,
+                                   const MatchFinder::MatchResult &Result) {
+  ExpansionRanges Locs;
+  while (Loc.isMacroID()) {
+    Locs.push_back(Result.SourceManager->getImmediateExpansionRange(Loc));
+    Loc = Locs.back().first;
+  }
+  return Locs;
+}
+
+} // namespace
+
+void MultipleStatementMacroCheck::registerMatchers(MatchFinder *Finder) {
+  const auto Inner = expr(isInMacro(), unless(compoundStmt())).bind("inner");
+  Finder->addMatcher(
+      stmt(anyOf(ifStmt(hasThen(Inner)), ifStmt(hasElse(Inner)).bind("else"),
+                 whileStmt(hasBody(Inner)), forStmt(hasBody(Inner))))
+          .bind("outer"),
+      this);
+}
+
+void MultipleStatementMacroCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *Inner = Result.Nodes.getNodeAs<Expr>("inner");
+  const auto *Outer = Result.Nodes.getNodeAs<Stmt>("outer");
+  const auto *Next = nextStmt(Result, Outer);
+  if (!Next)
+    return;
+
+  SourceLocation OuterLoc = Outer->getLocStart();
+  if (Result.Nodes.getNodeAs<Stmt>("else"))
+    OuterLoc = cast<IfStmt>(Outer)->getElseLoc();
+
+  auto InnerRanges = getExpansionRanges(Inner->getLocStart(), Result);
+  auto OuterRanges = getExpansionRanges(OuterLoc, Result);
+  auto NextRanges = getExpansionRanges(Next->getLocStart(), Result);
+
+  // Remove all the common ranges, starting from the top (the last ones in the
+  // list).
+  while (!InnerRanges.empty() && !OuterRanges.empty() && !NextRanges.empty() &&
+         InnerRanges.back() == OuterRanges.back() &&
+         InnerRanges.back() == NextRanges.back()) {
+    InnerRanges.pop_back();
+    OuterRanges.pop_back();
+    NextRanges.pop_back();
+  }
+
+  // Inner and Next must have at least one more macro that Outer doesn't have,
+  // and that range must be common to both.
+  if (InnerRanges.empty() || NextRanges.empty() ||
+      InnerRanges.back() != NextRanges.back())
+    return;
+
+  diag(InnerRanges.back().first, "multiple statement macro used without "
+                                 "braces; some statements will be "
+                                 "unconditionally executed");
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/bugprone/MultipleStatementMacroCheck.h b/clang-tools-extra/clang-tidy/bugprone/MultipleStatementMacroCheck.h
new file mode 100644
index 0000000..efc6599
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/MultipleStatementMacroCheck.h
@@ -0,0 +1,37 @@
+//===--- MultipleStatementMacroCheck.h - clang-tidy--------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MULTIPLE_STATEMENT_MACRO_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MULTIPLE_STATEMENT_MACRO_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Detect multiple statement macros that are used in unbraced conditionals.
+/// Only the first statement of the macro will be inside the conditional and the
+/// other ones will be executed unconditionally.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-multiple-statement-macro.html
+class MultipleStatementMacroCheck : public ClangTidyCheck {
+public:
+  MultipleStatementMacroCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MULTIPLE_STATEMENT_MACRO_H
diff --git a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp
new file mode 100644
index 0000000..6fa4cab
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp
@@ -0,0 +1,434 @@
+//===--- UseAfterMoveCheck.cpp - clang-tidy -------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "UseAfterMoveCheck.h"
+
+#include "clang/Analysis/CFG.h"
+#include "clang/Lex/Lexer.h"
+
+#include "../utils/ExprSequence.h"
+
+using namespace clang::ast_matchers;
+using namespace clang::tidy::utils;
+
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+namespace {
+
+/// Contains information about a use-after-move.
+struct UseAfterMove {
+  // The DeclRefExpr that constituted the use of the object.
+  const DeclRefExpr *DeclRef;
+
+  // Is the order in which the move and the use are evaluated undefined?
+  bool EvaluationOrderUndefined;
+};
+
+/// Finds uses of a variable after a move (and maintains state required by the
+/// various internal helper functions).
+class UseAfterMoveFinder {
+public:
+  UseAfterMoveFinder(ASTContext *TheContext);
+
+  // Within the given function body, finds the first use of 'MovedVariable' that
+  // occurs after 'MovingCall' (the expression that performs the move). If a
+  // use-after-move is found, writes information about it to 'TheUseAfterMove'.
+  // Returns whether a use-after-move was found.
+  bool find(Stmt *FunctionBody, const Expr *MovingCall,
+            const ValueDecl *MovedVariable, UseAfterMove *TheUseAfterMove);
+
+private:
+  bool findInternal(const CFGBlock *Block, const Expr *MovingCall,
+                    const ValueDecl *MovedVariable,
+                    UseAfterMove *TheUseAfterMove);
+  void getUsesAndReinits(const CFGBlock *Block, const ValueDecl *MovedVariable,
+                         llvm::SmallVectorImpl<const DeclRefExpr *> *Uses,
+                         llvm::SmallPtrSetImpl<const Stmt *> *Reinits);
+  void getDeclRefs(const CFGBlock *Block, const Decl *MovedVariable,
+                   llvm::SmallPtrSetImpl<const DeclRefExpr *> *DeclRefs);
+  void getReinits(const CFGBlock *Block, const ValueDecl *MovedVariable,
+                  llvm::SmallPtrSetImpl<const Stmt *> *Stmts,
+                  llvm::SmallPtrSetImpl<const DeclRefExpr *> *DeclRefs);
+
+  ASTContext *Context;
+  std::unique_ptr<ExprSequence> Sequence;
+  std::unique_ptr<StmtToBlockMap> BlockMap;
+  llvm::SmallPtrSet<const CFGBlock *, 8> Visited;
+};
+
+} // namespace
+
+
+// Matches nodes that are
+// - Part of a decltype argument or class template argument (we check this by
+//   seeing if they are children of a TypeLoc), or
+// - Part of a function template argument (we check this by seeing if they are
+//   children of a DeclRefExpr that references a function template).
+// DeclRefExprs that fulfill these conditions should not be counted as a use or
+// move.
+static StatementMatcher inDecltypeOrTemplateArg() {
+  return anyOf(hasAncestor(typeLoc()),
+               hasAncestor(declRefExpr(
+                   to(functionDecl(ast_matchers::isTemplateInstantiation())))));
+}
+
+UseAfterMoveFinder::UseAfterMoveFinder(ASTContext *TheContext)
+    : Context(TheContext) {}
+
+bool UseAfterMoveFinder::find(Stmt *FunctionBody, const Expr *MovingCall,
+                              const ValueDecl *MovedVariable,
+                              UseAfterMove *TheUseAfterMove) {
+  // Generate the CFG manually instead of through an AnalysisDeclContext because
+  // it seems the latter can't be used to generate a CFG for the body of a
+  // labmda.
+  //
+  // We include implicit and temporary destructors in the CFG so that
+  // destructors marked [[noreturn]] are handled correctly in the control flow
+  // analysis. (These are used in some styles of assertion macros.)
+  CFG::BuildOptions Options;
+  Options.AddImplicitDtors = true;
+  Options.AddTemporaryDtors = true;
+  std::unique_ptr<CFG> TheCFG =
+      CFG::buildCFG(nullptr, FunctionBody, Context, Options);
+  if (!TheCFG)
+    return false;
+
+  Sequence.reset(new ExprSequence(TheCFG.get(), Context));
+  BlockMap.reset(new StmtToBlockMap(TheCFG.get(), Context));
+  Visited.clear();
+
+  const CFGBlock *Block = BlockMap->blockContainingStmt(MovingCall);
+  if (!Block)
+    return false;
+
+  return findInternal(Block, MovingCall, MovedVariable, TheUseAfterMove);
+}
+
+bool UseAfterMoveFinder::findInternal(const CFGBlock *Block,
+                                      const Expr *MovingCall,
+                                      const ValueDecl *MovedVariable,
+                                      UseAfterMove *TheUseAfterMove) {
+  if (Visited.count(Block))
+    return false;
+
+  // Mark the block as visited (except if this is the block containing the
+  // std::move() and it's being visited the first time).
+  if (!MovingCall)
+    Visited.insert(Block);
+
+  // Get all uses and reinits in the block.
+  llvm::SmallVector<const DeclRefExpr *, 1> Uses;
+  llvm::SmallPtrSet<const Stmt *, 1> Reinits;
+  getUsesAndReinits(Block, MovedVariable, &Uses, &Reinits);
+
+  // Ignore all reinitializations where the move potentially comes after the
+  // reinit.
+  llvm::SmallVector<const Stmt *, 1> ReinitsToDelete;
+  for (const Stmt *Reinit : Reinits) {
+    if (MovingCall && Sequence->potentiallyAfter(MovingCall, Reinit))
+      ReinitsToDelete.push_back(Reinit);
+  }
+  for (const Stmt *Reinit : ReinitsToDelete) {
+    Reinits.erase(Reinit);
+  }
+
+  // Find all uses that potentially come after the move.
+  for (const DeclRefExpr *Use : Uses) {
+    if (!MovingCall || Sequence->potentiallyAfter(Use, MovingCall)) {
+      // Does the use have a saving reinit? A reinit is saving if it definitely
+      // comes before the use, i.e. if there's no potential that the reinit is
+      // after the use.
+      bool HaveSavingReinit = false;
+      for (const Stmt *Reinit : Reinits) {
+        if (!Sequence->potentiallyAfter(Reinit, Use))
+          HaveSavingReinit = true;
+      }
+
+      if (!HaveSavingReinit) {
+        TheUseAfterMove->DeclRef = Use;
+
+        // Is this a use-after-move that depends on order of evaluation?
+        // This is the case if the move potentially comes after the use (and we
+        // already know that use potentially comes after the move, which taken
+        // together tells us that the ordering is unclear).
+        TheUseAfterMove->EvaluationOrderUndefined =
+            MovingCall != nullptr &&
+            Sequence->potentiallyAfter(MovingCall, Use);
+
+        return true;
+      }
+    }
+  }
+
+  // If the object wasn't reinitialized, call ourselves recursively on all
+  // successors.
+  if (Reinits.empty()) {
+    for (const auto &Succ : Block->succs()) {
+      if (Succ && findInternal(Succ, nullptr, MovedVariable, TheUseAfterMove))
+        return true;
+    }
+  }
+
+  return false;
+}
+
+void UseAfterMoveFinder::getUsesAndReinits(
+    const CFGBlock *Block, const ValueDecl *MovedVariable,
+    llvm::SmallVectorImpl<const DeclRefExpr *> *Uses,
+    llvm::SmallPtrSetImpl<const Stmt *> *Reinits) {
+  llvm::SmallPtrSet<const DeclRefExpr *, 1> DeclRefs;
+  llvm::SmallPtrSet<const DeclRefExpr *, 1> ReinitDeclRefs;
+
+  getDeclRefs(Block, MovedVariable, &DeclRefs);
+  getReinits(Block, MovedVariable, Reinits, &ReinitDeclRefs);
+
+  // All references to the variable that aren't reinitializations are uses.
+  Uses->clear();
+  for (const DeclRefExpr *DeclRef : DeclRefs) {
+    if (!ReinitDeclRefs.count(DeclRef))
+      Uses->push_back(DeclRef);
+  }
+
+  // Sort the uses by their occurrence in the source code.
+  std::sort(Uses->begin(), Uses->end(),
+            [](const DeclRefExpr *D1, const DeclRefExpr *D2) {
+              return D1->getExprLoc() < D2->getExprLoc();
+            });
+}
+
+bool isStandardSmartPointer(const ValueDecl *VD) {
+  const Type *TheType = VD->getType().getTypePtrOrNull();
+  if (!TheType)
+    return false;
+
+  const CXXRecordDecl *RecordDecl = TheType->getAsCXXRecordDecl();
+  if (!RecordDecl)
+    return false;
+
+  const IdentifierInfo *ID = RecordDecl->getIdentifier();
+  if (!ID)
+    return false;
+
+  StringRef Name = ID->getName();
+  if (Name != "unique_ptr" && Name != "shared_ptr" && Name != "weak_ptr")
+    return false;
+
+  return RecordDecl->getDeclContext()->isStdNamespace();
+}
+
+void UseAfterMoveFinder::getDeclRefs(
+    const CFGBlock *Block, const Decl *MovedVariable,
+    llvm::SmallPtrSetImpl<const DeclRefExpr *> *DeclRefs) {
+  DeclRefs->clear();
+  for (const auto &Elem : *Block) {
+    Optional<CFGStmt> S = Elem.getAs<CFGStmt>();
+    if (!S)
+      continue;
+
+    auto addDeclRefs = [this, Block,
+                        DeclRefs](const ArrayRef<BoundNodes> Matches) {
+      for (const auto &Match : Matches) {
+        const auto *DeclRef = Match.getNodeAs<DeclRefExpr>("declref");
+        const auto *Operator = Match.getNodeAs<CXXOperatorCallExpr>("operator");
+        if (DeclRef && BlockMap->blockContainingStmt(DeclRef) == Block) {
+          // Ignore uses of a standard smart pointer that don't dereference the
+          // pointer.
+          if (Operator || !isStandardSmartPointer(DeclRef->getDecl())) {
+            DeclRefs->insert(DeclRef);
+          }
+        }
+      }
+    };
+
+    auto DeclRefMatcher = declRefExpr(hasDeclaration(equalsNode(MovedVariable)),
+                                      unless(inDecltypeOrTemplateArg()))
+                              .bind("declref");
+
+    addDeclRefs(match(findAll(DeclRefMatcher), *S->getStmt(), *Context));
+    addDeclRefs(match(
+        findAll(cxxOperatorCallExpr(anyOf(hasOverloadedOperatorName("*"),
+                                          hasOverloadedOperatorName("->"),
+                                          hasOverloadedOperatorName("[]")),
+                                    hasArgument(0, DeclRefMatcher))
+                    .bind("operator")),
+        *S->getStmt(), *Context));
+  }
+}
+
+void UseAfterMoveFinder::getReinits(
+    const CFGBlock *Block, const ValueDecl *MovedVariable,
+    llvm::SmallPtrSetImpl<const Stmt *> *Stmts,
+    llvm::SmallPtrSetImpl<const DeclRefExpr *> *DeclRefs) {
+  auto DeclRefMatcher =
+      declRefExpr(hasDeclaration(equalsNode(MovedVariable))).bind("declref");
+
+  auto StandardContainerTypeMatcher = hasType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(cxxRecordDecl(hasAnyName(
+          "::std::basic_string", "::std::vector", "::std::deque",
+          "::std::forward_list", "::std::list", "::std::set", "::std::map",
+          "::std::multiset", "::std::multimap", "::std::unordered_set",
+          "::std::unordered_map", "::std::unordered_multiset",
+          "::std::unordered_multimap"))))));
+
+  auto StandardSmartPointerTypeMatcher = hasType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(cxxRecordDecl(hasAnyName(
+          "::std::unique_ptr", "::std::shared_ptr", "::std::weak_ptr"))))));
+
+  // Matches different types of reinitialization.
+  auto ReinitMatcher =
+      stmt(anyOf(
+               // Assignment. In addition to the overloaded assignment operator,
+               // test for built-in assignment as well, since template functions
+               // may be instantiated to use std::move() on built-in types.
+               binaryOperator(hasOperatorName("="), hasLHS(DeclRefMatcher)),
+               cxxOperatorCallExpr(hasOverloadedOperatorName("="),
+                                   hasArgument(0, DeclRefMatcher)),
+               // Declaration. We treat this as a type of reinitialization too,
+               // so we don't need to treat it separately.
+               declStmt(hasDescendant(equalsNode(MovedVariable))),
+               // clear() and assign() on standard containers.
+               cxxMemberCallExpr(
+                   on(allOf(DeclRefMatcher, StandardContainerTypeMatcher)),
+                   // To keep the matcher simple, we check for assign() calls
+                   // on all standard containers, even though only vector,
+                   // deque, forward_list and list have assign(). If assign()
+                   // is called on any of the other containers, this will be
+                   // flagged by a compile error anyway.
+                   callee(cxxMethodDecl(hasAnyName("clear", "assign")))),
+               // reset() on standard smart pointers.
+               cxxMemberCallExpr(
+                   on(allOf(DeclRefMatcher, StandardSmartPointerTypeMatcher)),
+                   callee(cxxMethodDecl(hasName("reset")))),
+               // Passing variable to a function as a non-const pointer.
+               callExpr(forEachArgumentWithParam(
+                   unaryOperator(hasOperatorName("&"),
+                                 hasUnaryOperand(DeclRefMatcher)),
+                   unless(parmVarDecl(hasType(pointsTo(isConstQualified())))))),
+               // Passing variable to a function as a non-const lvalue reference
+               // (unless that function is std::move()).
+               callExpr(forEachArgumentWithParam(
+                            DeclRefMatcher,
+                            unless(parmVarDecl(hasType(
+                                references(qualType(isConstQualified())))))),
+                        unless(callee(functionDecl(hasName("::std::move")))))))
+          .bind("reinit");
+
+  Stmts->clear();
+  DeclRefs->clear();
+  for (const auto &Elem : *Block) {
+    Optional<CFGStmt> S = Elem.getAs<CFGStmt>();
+    if (!S)
+      continue;
+
+    SmallVector<BoundNodes, 1> Matches =
+        match(findAll(ReinitMatcher), *S->getStmt(), *Context);
+
+    for (const auto &Match : Matches) {
+      const auto *TheStmt = Match.getNodeAs<Stmt>("reinit");
+      const auto *TheDeclRef = Match.getNodeAs<DeclRefExpr>("declref");
+      if (TheStmt && BlockMap->blockContainingStmt(TheStmt) == Block) {
+        Stmts->insert(TheStmt);
+
+        // We count DeclStmts as reinitializations, but they don't have a
+        // DeclRefExpr associated with them -- so we need to check 'TheDeclRef'
+        // before adding it to the set.
+        if (TheDeclRef)
+          DeclRefs->insert(TheDeclRef);
+      }
+    }
+  }
+}
+
+static void emitDiagnostic(const Expr *MovingCall, const DeclRefExpr *MoveArg,
+                           const UseAfterMove &Use, ClangTidyCheck *Check,
+                           ASTContext *Context) {
+  SourceLocation UseLoc = Use.DeclRef->getExprLoc();
+  SourceLocation MoveLoc = MovingCall->getExprLoc();
+
+  Check->diag(UseLoc, "'%0' used after it was moved")
+      << MoveArg->getDecl()->getName();
+  Check->diag(MoveLoc, "move occurred here", DiagnosticIDs::Note);
+  if (Use.EvaluationOrderUndefined) {
+    Check->diag(UseLoc,
+                "the use and move are unsequenced, i.e. there is no guarantee "
+                "about the order in which they are evaluated",
+                DiagnosticIDs::Note);
+  } else if (UseLoc < MoveLoc || Use.DeclRef == MoveArg) {
+    Check->diag(UseLoc,
+                "the use happens in a later loop iteration than the move",
+                DiagnosticIDs::Note);
+  }
+}
+
+void UseAfterMoveCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus11)
+    return;
+
+  auto CallMoveMatcher =
+      callExpr(callee(functionDecl(hasName("::std::move"))), argumentCountIs(1),
+               hasArgument(0, declRefExpr().bind("arg")),
+               anyOf(hasAncestor(lambdaExpr().bind("containing-lambda")),
+                     hasAncestor(functionDecl().bind("containing-func"))),
+               unless(inDecltypeOrTemplateArg()))
+          .bind("call-move");
+
+  Finder->addMatcher(
+      // To find the Stmt that we assume performs the actual move, we look for
+      // the direct ancestor of the std::move() that isn't one of the node
+      // types ignored by ignoringParenImpCasts().
+      stmt(forEach(expr(ignoringParenImpCasts(CallMoveMatcher))),
+           // Don't allow an InitListExpr to be the moving call. An InitListExpr
+           // has both a syntactic and a semantic form, and the parent-child
+           // relationships are different between the two. This could cause an
+           // InitListExpr to be analyzed as the moving call in addition to the
+           // Expr that we actually want, resulting in two diagnostics with
+           // different code locations for the same move.
+           unless(initListExpr()),
+           unless(expr(ignoringParenImpCasts(equalsBoundNode("call-move")))))
+          .bind("moving-call"),
+      this);
+}
+
+void UseAfterMoveCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *ContainingLambda =
+      Result.Nodes.getNodeAs<LambdaExpr>("containing-lambda");
+  const auto *ContainingFunc =
+      Result.Nodes.getNodeAs<FunctionDecl>("containing-func");
+  const auto *CallMove = Result.Nodes.getNodeAs<CallExpr>("call-move");
+  const auto *MovingCall = Result.Nodes.getNodeAs<Expr>("moving-call");
+  const auto *Arg = Result.Nodes.getNodeAs<DeclRefExpr>("arg");
+
+  if (!MovingCall || !MovingCall->getExprLoc().isValid())
+    MovingCall = CallMove;
+
+  Stmt *FunctionBody = nullptr;
+  if (ContainingLambda)
+    FunctionBody = ContainingLambda->getBody();
+  else if (ContainingFunc)
+    FunctionBody = ContainingFunc->getBody();
+  else
+    return;
+
+  // Ignore the std::move if the variable that was passed to it isn't a local
+  // variable.
+  if (!Arg->getDecl()->getDeclContext()->isFunctionOrMethod())
+    return;
+
+  UseAfterMoveFinder finder(Result.Context);
+  UseAfterMove Use;
+  if (finder.find(FunctionBody, MovingCall, Arg->getDecl(), &Use))
+    emitDiagnostic(MovingCall, Arg, Use, this, Result.Context);
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.h b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.h
new file mode 100644
index 0000000..f6dea68
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.h
@@ -0,0 +1,36 @@
+//===--- UseAfterMoveCheck.h - clang-tidy ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_USEAFTERMOVECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_USEAFTERMOVECHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// The check warns if an object is used after it has been moved, without an
+/// intervening reinitialization.
+///
+/// For details, see the user-facing documentation:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-use-after-move.html
+class UseAfterMoveCheck : public ClangTidyCheck {
+public:
+  UseAfterMoveCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_USEAFTERMOVECHECK_H
diff --git a/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp
new file mode 100644
index 0000000..6b3f498
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp
@@ -0,0 +1,274 @@
+//===--- VirtualNearMissCheck.cpp - clang-tidy-----------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "VirtualNearMissCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+AST_MATCHER(CXXMethodDecl, isStatic) { return Node.isStatic(); }
+
+AST_MATCHER(CXXMethodDecl, isOverloadedOperator) {
+  return Node.isOverloadedOperator();
+}
+
+/// Finds out if the given method overrides some method.
+static bool isOverrideMethod(const CXXMethodDecl *MD) {
+  return MD->size_overridden_methods() > 0 || MD->hasAttr<OverrideAttr>();
+}
+
+/// Checks whether the return types are covariant, according to
+/// C++[class.virtual]p7.
+///
+/// Similar with clang::Sema::CheckOverridingFunctionReturnType.
+/// \returns true if the return types of BaseMD and DerivedMD are covariant.
+static bool checkOverridingFunctionReturnType(const ASTContext *Context,
+                                              const CXXMethodDecl *BaseMD,
+                                              const CXXMethodDecl *DerivedMD) {
+  QualType BaseReturnTy = BaseMD->getType()
+                              ->getAs<FunctionType>()
+                              ->getReturnType()
+                              .getCanonicalType();
+  QualType DerivedReturnTy = DerivedMD->getType()
+                                 ->getAs<FunctionType>()
+                                 ->getReturnType()
+                                 .getCanonicalType();
+
+  if (DerivedReturnTy->isDependentType() || BaseReturnTy->isDependentType())
+    return false;
+
+  // Check if return types are identical.
+  if (Context->hasSameType(DerivedReturnTy, BaseReturnTy))
+    return true;
+
+  /// Check if the return types are covariant.
+
+  // Both types must be pointers or references to classes.
+  if (!(BaseReturnTy->isPointerType() && DerivedReturnTy->isPointerType()) &&
+      !(BaseReturnTy->isReferenceType() && DerivedReturnTy->isReferenceType()))
+    return false;
+
+  /// BTy is the class type in return type of BaseMD. For example,
+  ///    B* Base::md()
+  /// While BRD is the declaration of B.
+  QualType DTy = DerivedReturnTy->getPointeeType().getCanonicalType();
+  QualType BTy = BaseReturnTy->getPointeeType().getCanonicalType();
+
+  const CXXRecordDecl *DRD = DTy->getAsCXXRecordDecl();
+  const CXXRecordDecl *BRD = BTy->getAsCXXRecordDecl();
+  if (DRD == nullptr || BRD == nullptr)
+    return false;
+
+  if (!DRD->hasDefinition() || !BRD->hasDefinition())
+    return false;
+
+  if (DRD == BRD)
+    return true;
+
+  if (!Context->hasSameUnqualifiedType(DTy, BTy)) {
+    // Begin checking whether the conversion from D to B is valid.
+    CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+                       /*DetectVirtual=*/false);
+
+    // Check whether D is derived from B, and fill in a CXXBasePaths object.
+    if (!DRD->isDerivedFrom(BRD, Paths))
+      return false;
+
+    // Check ambiguity.
+    if (Paths.isAmbiguous(Context->getCanonicalType(BTy).getUnqualifiedType()))
+      return false;
+
+    // Check accessibility.
+    // FIXME: We currently only support checking if B is accessible base class
+    // of D, or D is the same class which DerivedMD is in.
+    bool IsItself =
+        DRD->getCanonicalDecl() == DerivedMD->getParent()->getCanonicalDecl();
+    bool HasPublicAccess = false;
+    for (const auto &Path : Paths) {
+      if (Path.Access == AS_public)
+        HasPublicAccess = true;
+    }
+    if (!HasPublicAccess && !IsItself)
+      return false;
+    // End checking conversion from D to B.
+  }
+
+  // Both pointers or references should have the same cv-qualification.
+  if (DerivedReturnTy.getLocalCVRQualifiers() !=
+      BaseReturnTy.getLocalCVRQualifiers())
+    return false;
+
+  // The class type D should have the same cv-qualification as or less
+  // cv-qualification than the class type B.
+  if (DTy.isMoreQualifiedThan(BTy))
+    return false;
+
+  return true;
+}
+
+/// \returns decayed type for arrays and functions.
+static QualType getDecayedType(QualType Type) {
+  if (const auto *Decayed = Type->getAs<DecayedType>())
+    return Decayed->getDecayedType();
+  return Type;
+}
+
+/// \returns true if the param types are the same.
+static bool checkParamTypes(const CXXMethodDecl *BaseMD,
+                            const CXXMethodDecl *DerivedMD) {
+  unsigned NumParamA = BaseMD->getNumParams();
+  unsigned NumParamB = DerivedMD->getNumParams();
+  if (NumParamA != NumParamB)
+    return false;
+
+  for (unsigned I = 0; I < NumParamA; I++) {
+    if (getDecayedType(BaseMD->getParamDecl(I)->getType().getCanonicalType()) !=
+        getDecayedType(
+            DerivedMD->getParamDecl(I)->getType().getCanonicalType()))
+      return false;
+  }
+  return true;
+}
+
+/// \returns true if derived method can override base method except for the
+/// name.
+static bool checkOverrideWithoutName(const ASTContext *Context,
+                                     const CXXMethodDecl *BaseMD,
+                                     const CXXMethodDecl *DerivedMD) {
+  if (BaseMD->isStatic() != DerivedMD->isStatic())
+    return false;
+
+  if (BaseMD->getType() == DerivedMD->getType())
+    return true;
+
+  // Now the function types are not identical. Then check if the return types
+  // are covariant and if the param types are the same.
+  if (!checkOverridingFunctionReturnType(Context, BaseMD, DerivedMD))
+    return false;
+  return checkParamTypes(BaseMD, DerivedMD);
+}
+
+/// Check whether BaseMD overrides DerivedMD.
+///
+/// Prerequisite: the class which BaseMD is in should be a base class of that
+/// DerivedMD is in.
+static bool checkOverrideByDerivedMethod(const CXXMethodDecl *BaseMD,
+                                         const CXXMethodDecl *DerivedMD) {
+  for (CXXMethodDecl::method_iterator I = DerivedMD->begin_overridden_methods(),
+                                      E = DerivedMD->end_overridden_methods();
+       I != E; ++I) {
+    const CXXMethodDecl *OverriddenMD = *I;
+    if (BaseMD->getCanonicalDecl() == OverriddenMD->getCanonicalDecl())
+      return true;
+  }
+
+  return false;
+}
+
+bool VirtualNearMissCheck::isPossibleToBeOverridden(
+    const CXXMethodDecl *BaseMD) {
+  auto Iter = PossibleMap.find(BaseMD);
+  if (Iter != PossibleMap.end())
+    return Iter->second;
+
+  bool IsPossible = !BaseMD->isImplicit() && !isa<CXXConstructorDecl>(BaseMD) &&
+                    !isa<CXXDestructorDecl>(BaseMD) && BaseMD->isVirtual() &&
+                    !BaseMD->isOverloadedOperator() &&
+                    !isa<CXXConversionDecl>(BaseMD);
+  PossibleMap[BaseMD] = IsPossible;
+  return IsPossible;
+}
+
+bool VirtualNearMissCheck::isOverriddenByDerivedClass(
+    const CXXMethodDecl *BaseMD, const CXXRecordDecl *DerivedRD) {
+  auto Key = std::make_pair(BaseMD, DerivedRD);
+  auto Iter = OverriddenMap.find(Key);
+  if (Iter != OverriddenMap.end())
+    return Iter->second;
+
+  bool IsOverridden = false;
+  for (const CXXMethodDecl *DerivedMD : DerivedRD->methods()) {
+    if (!isOverrideMethod(DerivedMD))
+      continue;
+
+    if (checkOverrideByDerivedMethod(BaseMD, DerivedMD)) {
+      IsOverridden = true;
+      break;
+    }
+  }
+  OverriddenMap[Key] = IsOverridden;
+  return IsOverridden;
+}
+
+void VirtualNearMissCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  Finder->addMatcher(
+      cxxMethodDecl(
+          unless(anyOf(isOverride(), isImplicit(), cxxConstructorDecl(),
+                       cxxDestructorDecl(), cxxConversionDecl(), isStatic(),
+                       isOverloadedOperator())))
+          .bind("method"),
+      this);
+}
+
+void VirtualNearMissCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *DerivedMD = Result.Nodes.getNodeAs<CXXMethodDecl>("method");
+  assert(DerivedMD);
+
+  const ASTContext *Context = Result.Context;
+
+  const auto *DerivedRD = DerivedMD->getParent()->getDefinition();
+  assert(DerivedRD);
+
+  for (const auto &BaseSpec : DerivedRD->bases()) {
+    if (const auto *BaseRD = BaseSpec.getType()->getAsCXXRecordDecl()) {
+      for (const auto *BaseMD : BaseRD->methods()) {
+        if (!isPossibleToBeOverridden(BaseMD))
+          continue;
+
+        if (isOverriddenByDerivedClass(BaseMD, DerivedRD))
+          continue;
+
+        unsigned EditDistance = BaseMD->getName().edit_distance(
+            DerivedMD->getName(), EditDistanceThreshold);
+        if (EditDistance > 0 && EditDistance <= EditDistanceThreshold) {
+          if (checkOverrideWithoutName(Context, BaseMD, DerivedMD)) {
+            // A "virtual near miss" is found.
+            auto Range = CharSourceRange::getTokenRange(
+                SourceRange(DerivedMD->getLocation()));
+
+            bool ApplyFix = !BaseMD->isTemplateInstantiation() &&
+                            !DerivedMD->isTemplateInstantiation();
+            auto Diag =
+                diag(DerivedMD->getLocStart(),
+                     "method '%0' has a similar name and the same signature as "
+                     "virtual method '%1'; did you mean to override it?")
+                << DerivedMD->getQualifiedNameAsString()
+                << BaseMD->getQualifiedNameAsString();
+            if (ApplyFix)
+              Diag << FixItHint::CreateReplacement(Range, BaseMD->getName());
+          }
+        }
+      }
+    }
+  }
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.h b/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.h
new file mode 100644
index 0000000..ea1e256
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.h
@@ -0,0 +1,65 @@
+//===--- VirtualNearMissCheck.h - clang-tidy---------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_VIRTUAL_NEAR_MISS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_VIRTUAL_NEAR_MISS_H
+
+#include "../ClangTidy.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// \brief Checks for near miss of virtual methods.
+///
+/// For a method in a derived class, this check looks for virtual method with a
+/// very similar name and an identical signature defined in a base class.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-virtual-near-miss.html
+class VirtualNearMissCheck : public ClangTidyCheck {
+public:
+  VirtualNearMissCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  /// Check if the given method is possible to be overridden by some other
+  /// method. Operators and destructors are excluded.
+  ///
+  /// Results are memoized in PossibleMap.
+  bool isPossibleToBeOverridden(const CXXMethodDecl *BaseMD);
+
+  /// Check if the given base method is overridden by some methods in the given
+  /// derived class.
+  ///
+  /// Results are memoized in OverriddenMap.
+  bool isOverriddenByDerivedClass(const CXXMethodDecl *BaseMD,
+                                  const CXXRecordDecl *DerivedRD);
+
+  /// Key: the unique ID of a method.
+  /// Value: whether the method is possible to be overridden.
+  llvm::DenseMap<const CXXMethodDecl *, bool> PossibleMap;
+
+  /// Key: <unique ID of base method, name of derived class>
+  /// Value: whether the base method is overridden by some method in the derived
+  /// class.
+  llvm::DenseMap<std::pair<const CXXMethodDecl *, const CXXRecordDecl *>, bool>
+      OverriddenMap;
+
+  const unsigned EditDistanceThreshold = 1;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_VIRTUAL_NEAR_MISS_H