Merge 47651f32 for LLVM update to 316199

Change-Id: I66c1048d534983bdf966ede3c00cf06a318c6b47
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ec70fd1..760340a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,4 @@
 add_subdirectory(clang-apply-replacements)
-add_subdirectory(clang-rename)
 add_subdirectory(clang-reorder-fields)
 add_subdirectory(modularize)
 if(CLANG_ENABLE_STATIC_ANALYZER)
@@ -16,8 +15,7 @@
 add_subdirectory(tool-template)
 
 # Add the common testsuite after all the tools.
-# TODO: Support tests with more granularity when features are off?
-if(CLANG_ENABLE_STATIC_ANALYZER AND CLANG_INCLUDE_TESTS)
+if(CLANG_INCLUDE_TESTS)
 add_subdirectory(test)
 add_subdirectory(unittests)
 endif()
diff --git a/change-namespace/ChangeNamespace.cpp b/change-namespace/ChangeNamespace.cpp
index 0b90de4..bb3867c 100644
--- a/change-namespace/ChangeNamespace.cpp
+++ b/change-namespace/ChangeNamespace.cpp
@@ -427,7 +427,8 @@
                                      unless(templateSpecializationType())))))),
                            hasParent(nestedNameSpecifierLoc()),
                            hasAncestor(isImplicit()),
-                           hasAncestor(UsingShadowDeclInClass))),
+                           hasAncestor(UsingShadowDeclInClass),
+                           hasAncestor(functionDecl(isDefaulted())))),
               hasAncestor(decl().bind("dc")))
           .bind("type"),
       this);
@@ -451,6 +452,7 @@
               specifiesType(hasDeclaration(DeclMatcher.bind("from_decl"))))),
           unless(anyOf(hasAncestor(isImplicit()),
                        hasAncestor(UsingShadowDeclInClass),
+                       hasAncestor(functionDecl(isDefaulted())),
                        hasAncestor(typeLoc(loc(qualType(hasDeclaration(
                            decl(equalsBoundNode("from_decl"))))))))))
           .bind("nested_specifier_loc"),
diff --git a/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp b/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp
index 52234fe..56482dc 100644
--- a/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp
+++ b/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp
@@ -288,13 +288,12 @@
     for (const tooling::Replacement &R : TU.Replacements) {
       // Use the file manager to deduplicate paths. FileEntries are
       // automatically canonicalized.
-      const FileEntry *Entry = SM.getFileManager().getFile(R.getFilePath());
-      if (!Entry && Warned.insert(R.getFilePath()).second) {
-        errs() << "Described file '" << R.getFilePath()
-               << "' doesn't exist. Ignoring...\n";
-        continue;
+      if (const FileEntry *Entry = SM.getFileManager().getFile(R.getFilePath())) {
+        GroupedReplacements[Entry].push_back(R);
+      } else if (Warned.insert(R.getFilePath()).second) {
+          errs() << "Described file '" << R.getFilePath()
+                 << "' doesn't exist. Ignoring...\n";
       }
-      GroupedReplacements[Entry].push_back(R);
     }
   }
 
@@ -314,13 +313,12 @@
         for (const tooling::Replacement &R : Fix.second) {
           // Use the file manager to deduplicate paths. FileEntries are
           // automatically canonicalized.
-          const FileEntry *Entry = SM.getFileManager().getFile(R.getFilePath());
-          if (!Entry && Warned.insert(R.getFilePath()).second) {
-            errs() << "Described file '" << R.getFilePath()
-                   << "' doesn't exist. Ignoring...\n";
-            continue;
+          if (const FileEntry *Entry = SM.getFileManager().getFile(R.getFilePath())) {
+            GroupedReplacements[Entry].push_back(R);
+          } else if (Warned.insert(R.getFilePath()).second) {
+              errs() << "Described file '" << R.getFilePath()
+                     << "' doesn't exist. Ignoring...\n";
           }
-          GroupedReplacements[Entry].push_back(R);
         }
       }
     }
diff --git a/clang-query/Query.cpp b/clang-query/Query.cpp
index b3344da..072ee6b 100644
--- a/clang-query/Query.cpp
+++ b/clang-query/Query.cpp
@@ -97,10 +97,10 @@
           if (R.isValid()) {
             TextDiagnostic TD(OS, AST->getASTContext().getLangOpts(),
                               &AST->getDiagnostics().getDiagnosticOptions());
-            TD.emitDiagnostic(R.getBegin(), DiagnosticsEngine::Note,
-                              "\"" + BI->first + "\" binds here",
-                              CharSourceRange::getTokenRange(R), None,
-                              &AST->getSourceManager());
+            TD.emitDiagnostic(
+                FullSourceLoc(R.getBegin(), AST->getSourceManager()),
+                DiagnosticsEngine::Note, "\"" + BI->first + "\" binds here",
+                CharSourceRange::getTokenRange(R), None);
           }
           break;
         }
diff --git a/clang-rename/CMakeLists.txt b/clang-rename/CMakeLists.txt
deleted file mode 100644
index 84e7951..0000000
--- a/clang-rename/CMakeLists.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-set(LLVM_LINK_COMPONENTS support)
-
-add_clang_library(clangRename
-  USRFinder.cpp
-  USRFindingAction.cpp
-  USRLocFinder.cpp
-  RenamingAction.cpp
-
-  LINK_LIBS
-  clangAST
-  clangASTMatchers
-  clangBasic
-  clangIndex
-  clangLex
-  clangToolingCore
-  clangToolingRefactor
-  )
-
-add_subdirectory(tool)
diff --git a/clang-rename/RenamingAction.cpp b/clang-rename/RenamingAction.cpp
deleted file mode 100644
index fac0416..0000000
--- a/clang-rename/RenamingAction.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-//===--- tools/extra/clang-rename/RenamingAction.cpp - Clang rename tool --===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Provides an action to rename every symbol at a point.
-///
-//===----------------------------------------------------------------------===//
-
-#include "RenamingAction.h"
-#include "USRLocFinder.h"
-#include "clang/AST/ASTConsumer.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Frontend/FrontendAction.h"
-#include "clang/Lex/Lexer.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Tooling/CommonOptionsParser.h"
-#include "clang/Tooling/Refactoring.h"
-#include "clang/Tooling/Tooling.h"
-#include <string>
-#include <vector>
-
-using namespace llvm;
-
-namespace clang {
-namespace rename {
-
-class RenamingASTConsumer : public ASTConsumer {
-public:
-  RenamingASTConsumer(
-      const std::vector<std::string> &NewNames,
-      const std::vector<std::string> &PrevNames,
-      const std::vector<std::vector<std::string>> &USRList,
-      std::map<std::string, tooling::Replacements> &FileToReplaces,
-      bool PrintLocations)
-      : NewNames(NewNames), PrevNames(PrevNames), USRList(USRList),
-        FileToReplaces(FileToReplaces), PrintLocations(PrintLocations) {}
-
-  void HandleTranslationUnit(ASTContext &Context) override {
-    for (unsigned I = 0; I < NewNames.size(); ++I)
-      HandleOneRename(Context, NewNames[I], PrevNames[I], USRList[I]);
-  }
-
-  void HandleOneRename(ASTContext &Context, const std::string &NewName,
-                       const std::string &PrevName,
-                       const std::vector<std::string> &USRs) {
-    const SourceManager &SourceMgr = Context.getSourceManager();
-    std::vector<SourceLocation> RenamingCandidates;
-    std::vector<SourceLocation> NewCandidates;
-
-    NewCandidates =
-        getLocationsOfUSRs(USRs, PrevName, Context.getTranslationUnitDecl());
-    RenamingCandidates.insert(RenamingCandidates.end(), NewCandidates.begin(),
-                              NewCandidates.end());
-
-    unsigned PrevNameLen = PrevName.length();
-    for (const auto &Loc : RenamingCandidates) {
-      if (PrintLocations) {
-        FullSourceLoc FullLoc(Loc, SourceMgr);
-        errs() << "clang-rename: renamed at: " << SourceMgr.getFilename(Loc)
-               << ":" << FullLoc.getSpellingLineNumber() << ":"
-               << FullLoc.getSpellingColumnNumber() << "\n";
-      }
-      // FIXME: better error handling.
-      tooling::Replacement Replace(SourceMgr, Loc, PrevNameLen, NewName);
-      llvm::Error Err = FileToReplaces[Replace.getFilePath()].add(Replace);
-      if (Err)
-        llvm::errs() << "Renaming failed in " << Replace.getFilePath() << "! "
-                     << llvm::toString(std::move(Err)) << "\n";
-    }
-  }
-
-private:
-  const std::vector<std::string> &NewNames, &PrevNames;
-  const std::vector<std::vector<std::string>> &USRList;
-  std::map<std::string, tooling::Replacements> &FileToReplaces;
-  bool PrintLocations;
-};
-
-// A renamer to rename symbols which are identified by a give USRList to
-// new name.
-//
-// FIXME: Merge with the above RenamingASTConsumer.
-class USRSymbolRenamer : public ASTConsumer {
-public:
-  USRSymbolRenamer(const std::vector<std::string> &NewNames,
-                   const std::vector<std::vector<std::string>> &USRList,
-                   std::map<std::string, tooling::Replacements> &FileToReplaces)
-      : NewNames(NewNames), USRList(USRList), FileToReplaces(FileToReplaces) {
-    assert(USRList.size() == NewNames.size());
-  }
-
-  void HandleTranslationUnit(ASTContext &Context) override {
-    for (unsigned I = 0; I < NewNames.size(); ++I) {
-      // FIXME: Apply AtomicChanges directly once the refactoring APIs are
-      // ready.
-      auto AtomicChanges = createRenameAtomicChanges(
-          USRList[I], NewNames[I], Context.getTranslationUnitDecl());
-      for (const auto AtomicChange : AtomicChanges) {
-        for (const auto &Replace : AtomicChange.getReplacements()) {
-          llvm::Error Err = FileToReplaces[Replace.getFilePath()].add(Replace);
-          if (Err) {
-            llvm::errs() << "Renaming failed in " << Replace.getFilePath()
-                         << "! " << llvm::toString(std::move(Err)) << "\n";
-          }
-        }
-      }
-    }
-  }
-
-private:
-  const std::vector<std::string> &NewNames;
-  const std::vector<std::vector<std::string>> &USRList;
-  std::map<std::string, tooling::Replacements> &FileToReplaces;
-};
-
-std::unique_ptr<ASTConsumer> RenamingAction::newASTConsumer() {
-  return llvm::make_unique<RenamingASTConsumer>(NewNames, PrevNames, USRList,
-                                                FileToReplaces, PrintLocations);
-}
-
-std::unique_ptr<ASTConsumer> QualifiedRenamingAction::newASTConsumer() {
-  return llvm::make_unique<USRSymbolRenamer>(NewNames, USRList, FileToReplaces);
-}
-
-} // namespace rename
-} // namespace clang
diff --git a/clang-rename/RenamingAction.h b/clang-rename/RenamingAction.h
deleted file mode 100644
index e8b98b2..0000000
--- a/clang-rename/RenamingAction.h
+++ /dev/null
@@ -1,70 +0,0 @@
-//===--- tools/extra/clang-rename/RenamingAction.h - Clang rename tool ----===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Provides an action to rename every symbol at a point.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_RENAMING_ACTION_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_RENAMING_ACTION_H
-
-#include "clang/Tooling/Refactoring.h"
-
-namespace clang {
-class ASTConsumer;
-class CompilerInstance;
-
-namespace rename {
-
-class RenamingAction {
-public:
-  RenamingAction(const std::vector<std::string> &NewNames,
-                 const std::vector<std::string> &PrevNames,
-                 const std::vector<std::vector<std::string>> &USRList,
-                 std::map<std::string, tooling::Replacements> &FileToReplaces,
-                 bool PrintLocations = false)
-      : NewNames(NewNames), PrevNames(PrevNames), USRList(USRList),
-        FileToReplaces(FileToReplaces), PrintLocations(PrintLocations) {}
-
-  std::unique_ptr<ASTConsumer> newASTConsumer();
-
-private:
-  const std::vector<std::string> &NewNames, &PrevNames;
-  const std::vector<std::vector<std::string>> &USRList;
-  std::map<std::string, tooling::Replacements> &FileToReplaces;
-  bool PrintLocations;
-};
-
-/// Rename all symbols identified by the given USRs.
-class QualifiedRenamingAction {
-public:
-  QualifiedRenamingAction(
-      const std::vector<std::string> &NewNames,
-      const std::vector<std::vector<std::string>> &USRList,
-      std::map<std::string, tooling::Replacements> &FileToReplaces)
-      : NewNames(NewNames), USRList(USRList), FileToReplaces(FileToReplaces) {}
-
-  std::unique_ptr<ASTConsumer> newASTConsumer();
-
-private:
-  /// New symbol names.
-  const std::vector<std::string> &NewNames;
-
-  /// A list of USRs. Each element represents USRs of a symbol being renamed.
-  const std::vector<std::vector<std::string>> &USRList;
-
-  /// A file path to replacements map.
-  std::map<std::string, tooling::Replacements> &FileToReplaces;
-};
-
-} // namespace rename
-} // namespace clang
-
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_RENAMING_ACTION_H
diff --git a/clang-rename/USRFinder.cpp b/clang-rename/USRFinder.cpp
deleted file mode 100644
index 901e402..0000000
--- a/clang-rename/USRFinder.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
-//===--- tools/extra/clang-rename/USRFinder.cpp - Clang rename tool -------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file Implements a recursive AST visitor that finds the USR of a symbol at a
-/// point.
-///
-//===----------------------------------------------------------------------===//
-
-#include "USRFinder.h"
-#include "clang/AST/AST.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
-#include "clang/Index/USRGeneration.h"
-#include "clang/Lex/Lexer.h"
-#include "llvm/ADT/SmallVector.h"
-
-using namespace llvm;
-
-namespace clang {
-namespace rename {
-
-// NamedDeclFindingASTVisitor recursively visits each AST node to find the
-// symbol underneath the cursor.
-// FIXME: move to separate .h/.cc file if this gets too large.
-namespace {
-class NamedDeclFindingASTVisitor
-    : public clang::RecursiveASTVisitor<NamedDeclFindingASTVisitor> {
-public:
-  // \brief Finds the NamedDecl at a point in the source.
-  // \param Point the location in the source to search for the NamedDecl.
-  explicit NamedDeclFindingASTVisitor(const SourceLocation Point,
-                                      const ASTContext &Context)
-      : Result(nullptr), Point(Point), Context(Context) {}
-
-  // \brief Finds the NamedDecl for a name in the source.
-  // \param Name the fully qualified name.
-  explicit NamedDeclFindingASTVisitor(const std::string &Name,
-                                      const ASTContext &Context)
-      : Result(nullptr), Name(Name), Context(Context) {}
-
-  // Declaration visitors:
-
-  // \brief Checks if the point falls within the NameDecl. This covers every
-  // declaration of a named entity that we may come across. Usually, just
-  // checking if the point lies within the length of the name of the declaration
-  // and the start location is sufficient.
-  bool VisitNamedDecl(const NamedDecl *Decl) {
-    return dyn_cast<CXXConversionDecl>(Decl)
-               ? true
-               : setResult(Decl, Decl->getLocation(),
-                           Decl->getNameAsString().length());
-  }
-
-  // Expression visitors:
-
-  bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
-    const NamedDecl *Decl = Expr->getFoundDecl();
-    return setResult(Decl, Expr->getLocation(),
-                     Decl->getNameAsString().length());
-  }
-
-  bool VisitMemberExpr(const MemberExpr *Expr) {
-    const NamedDecl *Decl = Expr->getFoundDecl().getDecl();
-    return setResult(Decl, Expr->getMemberLoc(),
-                     Decl->getNameAsString().length());
-  }
-
-  // Other visitors:
-
-  bool VisitTypeLoc(const TypeLoc Loc) {
-    const SourceLocation TypeBeginLoc = Loc.getBeginLoc();
-    const SourceLocation TypeEndLoc = Lexer::getLocForEndOfToken(
-        TypeBeginLoc, 0, Context.getSourceManager(), Context.getLangOpts());
-    if (const auto *TemplateTypeParm =
-            dyn_cast<TemplateTypeParmType>(Loc.getType()))
-      return setResult(TemplateTypeParm->getDecl(), TypeBeginLoc, TypeEndLoc);
-    if (const auto *TemplateSpecType =
-            dyn_cast<TemplateSpecializationType>(Loc.getType())) {
-      return setResult(TemplateSpecType->getTemplateName().getAsTemplateDecl(),
-                       TypeBeginLoc, TypeEndLoc);
-    }
-    return setResult(Loc.getType()->getAsCXXRecordDecl(), TypeBeginLoc,
-                     TypeEndLoc);
-  }
-
-  bool VisitCXXConstructorDecl(clang::CXXConstructorDecl *ConstructorDecl) {
-    for (const auto *Initializer : ConstructorDecl->inits()) {
-      // Ignore implicit initializers.
-      if (!Initializer->isWritten())
-        continue;
-      if (const clang::FieldDecl *FieldDecl = Initializer->getMember()) {
-        const SourceLocation InitBeginLoc = Initializer->getSourceLocation(),
-                             InitEndLoc = Lexer::getLocForEndOfToken(
-                                 InitBeginLoc, 0, Context.getSourceManager(),
-                                 Context.getLangOpts());
-        if (!setResult(FieldDecl, InitBeginLoc, InitEndLoc))
-          return false;
-      }
-    }
-    return true;
-  }
-
-  // Other:
-
-  const NamedDecl *getNamedDecl() { return Result; }
-
-  // \brief Determines if a namespace qualifier contains the point.
-  // \returns false on success and sets Result.
-  void handleNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) {
-    while (NameLoc) {
-      const NamespaceDecl *Decl =
-          NameLoc.getNestedNameSpecifier()->getAsNamespace();
-      setResult(Decl, NameLoc.getLocalBeginLoc(), NameLoc.getLocalEndLoc());
-      NameLoc = NameLoc.getPrefix();
-    }
-  }
-
-private:
-  // \brief Sets Result to Decl if the Point is within Start and End.
-  // \returns false on success.
-  bool setResult(const NamedDecl *Decl, SourceLocation Start,
-                 SourceLocation End) {
-    if (!Decl)
-      return true;
-    if (Name.empty()) {
-      // Offset is used to find the declaration.
-      if (!Start.isValid() || !Start.isFileID() || !End.isValid() ||
-          !End.isFileID() || !isPointWithin(Start, End))
-        return true;
-    } else {
-      // Fully qualified name is used to find the declaration.
-      if (Name != Decl->getQualifiedNameAsString() &&
-          Name != "::" + Decl->getQualifiedNameAsString())
-        return true;
-    }
-    Result = Decl;
-    return false;
-  }
-
-  // \brief Sets Result to Decl if Point is within Loc and Loc + Offset.
-  // \returns false on success.
-  bool setResult(const NamedDecl *Decl, SourceLocation Loc, unsigned Offset) {
-    // FIXME: Add test for Offset == 0. Add test for Offset - 1 (vs -2 etc).
-    return Offset == 0 ||
-           setResult(Decl, Loc, Loc.getLocWithOffset(Offset - 1));
-  }
-
-  // \brief Determines if the Point is within Start and End.
-  bool isPointWithin(const SourceLocation Start, const SourceLocation End) {
-    // FIXME: Add tests for Point == End.
-    return Point == Start || Point == End ||
-           (Context.getSourceManager().isBeforeInTranslationUnit(Start,
-                                                                 Point) &&
-            Context.getSourceManager().isBeforeInTranslationUnit(Point, End));
-  }
-
-  const NamedDecl *Result;
-  const SourceLocation Point; // The location to find the NamedDecl.
-  const std::string Name;
-  const ASTContext &Context;
-};
-} // namespace
-
-const NamedDecl *getNamedDeclAt(const ASTContext &Context,
-                                const SourceLocation Point) {
-  const SourceManager &SM = Context.getSourceManager();
-  NamedDeclFindingASTVisitor Visitor(Point, Context);
-
-  // Try to be clever about pruning down the number of top-level declarations we
-  // see. If both start and end is either before or after the point we're
-  // looking for the point cannot be inside of this decl. Don't even look at it.
-  for (auto *CurrDecl : Context.getTranslationUnitDecl()->decls()) {
-    SourceLocation StartLoc = CurrDecl->getLocStart();
-    SourceLocation EndLoc = CurrDecl->getLocEnd();
-    if (StartLoc.isValid() && EndLoc.isValid() &&
-        SM.isBeforeInTranslationUnit(StartLoc, Point) !=
-            SM.isBeforeInTranslationUnit(EndLoc, Point))
-      Visitor.TraverseDecl(CurrDecl);
-  }
-
-  NestedNameSpecifierLocFinder Finder(const_cast<ASTContext &>(Context));
-  for (const auto &Location : Finder.getNestedNameSpecifierLocations())
-    Visitor.handleNestedNameSpecifierLoc(Location);
-
-  return Visitor.getNamedDecl();
-}
-
-const NamedDecl *getNamedDeclFor(const ASTContext &Context,
-                                 const std::string &Name) {
-  NamedDeclFindingASTVisitor Visitor(Name, Context);
-  Visitor.TraverseDecl(Context.getTranslationUnitDecl());
-
-  return Visitor.getNamedDecl();
-}
-
-std::string getUSRForDecl(const Decl *Decl) {
-  llvm::SmallVector<char, 128> Buff;
-
-  // FIXME: Add test for the nullptr case.
-  if (Decl == nullptr || index::generateUSRForDecl(Decl, Buff))
-    return "";
-
-  return std::string(Buff.data(), Buff.size());
-}
-
-} // namespace rename
-} // namespace clang
diff --git a/clang-rename/USRFinder.h b/clang-rename/USRFinder.h
deleted file mode 100644
index 99ecda0..0000000
--- a/clang-rename/USRFinder.h
+++ /dev/null
@@ -1,84 +0,0 @@
-//===--- tools/extra/clang-rename/USRFinder.h - Clang rename tool ---------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Methods for determining the USR of a symbol at a location in source
-/// code.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDER_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDER_H
-
-#include "clang/AST/AST.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include <string>
-#include <vector>
-
-using namespace llvm;
-using namespace clang::ast_matchers;
-
-namespace clang {
-
-class ASTContext;
-class Decl;
-class SourceLocation;
-class NamedDecl;
-
-namespace rename {
-
-// Given an AST context and a point, returns a NamedDecl identifying the symbol
-// at the point. Returns null if nothing is found at the point.
-const NamedDecl *getNamedDeclAt(const ASTContext &Context,
-                                const SourceLocation Point);
-
-// Given an AST context and a fully qualified name, returns a NamedDecl
-// identifying the symbol with a matching name. Returns null if nothing is
-// found for the name.
-const NamedDecl *getNamedDeclFor(const ASTContext &Context,
-                                 const std::string &Name);
-
-// Converts a Decl into a USR.
-std::string getUSRForDecl(const Decl *Decl);
-
-// FIXME: Implement RecursiveASTVisitor<T>::VisitNestedNameSpecifier instead.
-class NestedNameSpecifierLocFinder : public MatchFinder::MatchCallback {
-public:
-  explicit NestedNameSpecifierLocFinder(ASTContext &Context)
-      : Context(Context) {}
-
-  std::vector<NestedNameSpecifierLoc> getNestedNameSpecifierLocations() {
-    addMatchers();
-    Finder.matchAST(Context);
-    return Locations;
-  }
-
-private:
-  void addMatchers() {
-    const auto NestedNameSpecifierLocMatcher =
-        nestedNameSpecifierLoc().bind("nestedNameSpecifierLoc");
-    Finder.addMatcher(NestedNameSpecifierLocMatcher, this);
-  }
-
-  void run(const MatchFinder::MatchResult &Result) override {
-    const auto *NNS = Result.Nodes.getNodeAs<NestedNameSpecifierLoc>(
-        "nestedNameSpecifierLoc");
-    Locations.push_back(*NNS);
-  }
-
-  ASTContext &Context;
-  std::vector<NestedNameSpecifierLoc> Locations;
-  MatchFinder Finder;
-};
-
-} // namespace rename
-} // namespace clang
-
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDER_H
diff --git a/clang-rename/USRFindingAction.cpp b/clang-rename/USRFindingAction.cpp
deleted file mode 100644
index 515acfb..0000000
--- a/clang-rename/USRFindingAction.cpp
+++ /dev/null
@@ -1,236 +0,0 @@
-//===--- tools/extra/clang-rename/USRFindingAction.cpp - Clang rename tool ===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Provides an action to find USR for the symbol at <offset>, as well as
-/// all additional USRs.
-///
-//===----------------------------------------------------------------------===//
-
-#include "USRFindingAction.h"
-#include "USRFinder.h"
-#include "clang/AST/AST.h"
-#include "clang/AST/ASTConsumer.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/RecursiveASTVisitor.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Frontend/FrontendAction.h"
-#include "clang/Lex/Lexer.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Tooling/CommonOptionsParser.h"
-#include "clang/Tooling/Refactoring.h"
-#include "clang/Tooling/Tooling.h"
-
-#include <algorithm>
-#include <set>
-#include <string>
-#include <vector>
-
-using namespace llvm;
-
-namespace clang {
-namespace rename {
-
-namespace {
-// \brief NamedDeclFindingConsumer should delegate finding USRs of given Decl to
-// AdditionalUSRFinder. AdditionalUSRFinder adds USRs of ctor and dtor if given
-// Decl refers to class and adds USRs of all overridden methods if Decl refers
-// to virtual method.
-class AdditionalUSRFinder : public RecursiveASTVisitor<AdditionalUSRFinder> {
-public:
-  AdditionalUSRFinder(const Decl *FoundDecl, ASTContext &Context)
-      : FoundDecl(FoundDecl), Context(Context) {}
-
-  std::vector<std::string> Find() {
-    // Fill OverriddenMethods and PartialSpecs storages.
-    TraverseDecl(Context.getTranslationUnitDecl());
-    if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(FoundDecl)) {
-      addUSRsOfOverridenFunctions(MethodDecl);
-      for (const auto &OverriddenMethod : OverriddenMethods) {
-        if (checkIfOverriddenFunctionAscends(OverriddenMethod))
-          USRSet.insert(getUSRForDecl(OverriddenMethod));
-      }
-    } else if (const auto *RecordDecl = dyn_cast<CXXRecordDecl>(FoundDecl)) {
-      handleCXXRecordDecl(RecordDecl);
-    } else if (const auto *TemplateDecl =
-                   dyn_cast<ClassTemplateDecl>(FoundDecl)) {
-      handleClassTemplateDecl(TemplateDecl);
-    } else {
-      USRSet.insert(getUSRForDecl(FoundDecl));
-    }
-    return std::vector<std::string>(USRSet.begin(), USRSet.end());
-  }
-
-  bool VisitCXXMethodDecl(const CXXMethodDecl *MethodDecl) {
-    if (MethodDecl->isVirtual())
-      OverriddenMethods.push_back(MethodDecl);
-    return true;
-  }
-
-  bool VisitClassTemplatePartialSpecializationDecl(
-      const ClassTemplatePartialSpecializationDecl *PartialSpec) {
-    PartialSpecs.push_back(PartialSpec);
-    return true;
-  }
-
-private:
-  void handleCXXRecordDecl(const CXXRecordDecl *RecordDecl) {
-    RecordDecl = RecordDecl->getDefinition();
-    if (const auto *ClassTemplateSpecDecl =
-            dyn_cast<ClassTemplateSpecializationDecl>(RecordDecl))
-      handleClassTemplateDecl(ClassTemplateSpecDecl->getSpecializedTemplate());
-    addUSRsOfCtorDtors(RecordDecl);
-  }
-
-  void handleClassTemplateDecl(const ClassTemplateDecl *TemplateDecl) {
-    for (const auto *Specialization : TemplateDecl->specializations())
-      addUSRsOfCtorDtors(Specialization);
-
-    for (const auto *PartialSpec : PartialSpecs) {
-      if (PartialSpec->getSpecializedTemplate() == TemplateDecl)
-        addUSRsOfCtorDtors(PartialSpec);
-    }
-    addUSRsOfCtorDtors(TemplateDecl->getTemplatedDecl());
-  }
-
-  void addUSRsOfCtorDtors(const CXXRecordDecl *RecordDecl) {
-    RecordDecl = RecordDecl->getDefinition();
-
-    // Skip if the CXXRecordDecl doesn't have definition.
-    if (!RecordDecl)
-      return;
-
-    for (const auto *CtorDecl : RecordDecl->ctors())
-      USRSet.insert(getUSRForDecl(CtorDecl));
-
-    USRSet.insert(getUSRForDecl(RecordDecl->getDestructor()));
-    USRSet.insert(getUSRForDecl(RecordDecl));
-  }
-
-  void addUSRsOfOverridenFunctions(const CXXMethodDecl *MethodDecl) {
-    USRSet.insert(getUSRForDecl(MethodDecl));
-    // Recursively visit each OverridenMethod.
-    for (const auto &OverriddenMethod : MethodDecl->overridden_methods())
-      addUSRsOfOverridenFunctions(OverriddenMethod);
-  }
-
-  bool checkIfOverriddenFunctionAscends(const CXXMethodDecl *MethodDecl) {
-    for (const auto &OverriddenMethod : MethodDecl->overridden_methods()) {
-      if (USRSet.find(getUSRForDecl(OverriddenMethod)) != USRSet.end())
-        return true;
-      return checkIfOverriddenFunctionAscends(OverriddenMethod);
-    }
-    return false;
-  }
-
-  const Decl *FoundDecl;
-  ASTContext &Context;
-  std::set<std::string> USRSet;
-  std::vector<const CXXMethodDecl *> OverriddenMethods;
-  std::vector<const ClassTemplatePartialSpecializationDecl *> PartialSpecs;
-};
-} // namespace
-
-class NamedDeclFindingConsumer : public ASTConsumer {
-public:
-  NamedDeclFindingConsumer(ArrayRef<unsigned> SymbolOffsets,
-                           ArrayRef<std::string> QualifiedNames,
-                           std::vector<std::string> &SpellingNames,
-                           std::vector<std::vector<std::string>> &USRList,
-                           bool Force, bool &ErrorOccurred)
-      : SymbolOffsets(SymbolOffsets), QualifiedNames(QualifiedNames),
-        SpellingNames(SpellingNames), USRList(USRList), Force(Force),
-        ErrorOccurred(ErrorOccurred) {}
-
-private:
-  bool FindSymbol(ASTContext &Context, const SourceManager &SourceMgr,
-                  unsigned SymbolOffset, const std::string &QualifiedName) {
-    DiagnosticsEngine &Engine = Context.getDiagnostics();
-    const FileID MainFileID = SourceMgr.getMainFileID();
-
-    if (SymbolOffset >= SourceMgr.getFileIDSize(MainFileID)) {
-      ErrorOccurred = true;
-      unsigned InvalidOffset = Engine.getCustomDiagID(
-          DiagnosticsEngine::Error,
-          "SourceLocation in file %0 at offset %1 is invalid");
-      Engine.Report(SourceLocation(), InvalidOffset)
-          << SourceMgr.getFileEntryForID(MainFileID)->getName() << SymbolOffset;
-      return false;
-    }
-
-    const SourceLocation Point = SourceMgr.getLocForStartOfFile(MainFileID)
-                                     .getLocWithOffset(SymbolOffset);
-    const NamedDecl *FoundDecl = QualifiedName.empty()
-                                     ? getNamedDeclAt(Context, Point)
-                                     : getNamedDeclFor(Context, QualifiedName);
-
-    if (FoundDecl == nullptr) {
-      if (QualifiedName.empty()) {
-        FullSourceLoc FullLoc(Point, SourceMgr);
-        unsigned CouldNotFindSymbolAt = Engine.getCustomDiagID(
-            DiagnosticsEngine::Error,
-            "clang-rename could not find symbol (offset %0)");
-        Engine.Report(Point, CouldNotFindSymbolAt) << SymbolOffset;
-        ErrorOccurred = true;
-        return false;
-      }
-
-      if (Force)
-        return true;
-
-      unsigned CouldNotFindSymbolNamed = Engine.getCustomDiagID(
-          DiagnosticsEngine::Error, "clang-rename could not find symbol %0");
-      Engine.Report(CouldNotFindSymbolNamed) << QualifiedName;
-      ErrorOccurred = true;
-      return false;
-    }
-
-    // If FoundDecl is a constructor or destructor, we want to instead take
-    // the Decl of the corresponding class.
-    if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(FoundDecl))
-      FoundDecl = CtorDecl->getParent();
-    else if (const auto *DtorDecl = dyn_cast<CXXDestructorDecl>(FoundDecl))
-      FoundDecl = DtorDecl->getParent();
-
-    SpellingNames.push_back(FoundDecl->getNameAsString());
-    AdditionalUSRFinder Finder(FoundDecl, Context);
-    USRList.push_back(Finder.Find());
-    return true;
-  }
-
-  void HandleTranslationUnit(ASTContext &Context) override {
-    const SourceManager &SourceMgr = Context.getSourceManager();
-    for (unsigned Offset : SymbolOffsets) {
-      if (!FindSymbol(Context, SourceMgr, Offset, ""))
-        return;
-    }
-    for (const std::string &QualifiedName : QualifiedNames) {
-      if (!FindSymbol(Context, SourceMgr, 0, QualifiedName))
-        return;
-    }
-  }
-
-  ArrayRef<unsigned> SymbolOffsets;
-  ArrayRef<std::string> QualifiedNames;
-  std::vector<std::string> &SpellingNames;
-  std::vector<std::vector<std::string>> &USRList;
-  bool Force;
-  bool &ErrorOccurred;
-};
-
-std::unique_ptr<ASTConsumer> USRFindingAction::newASTConsumer() {
-  return llvm::make_unique<NamedDeclFindingConsumer>(
-      SymbolOffsets, QualifiedNames, SpellingNames, USRList, Force,
-      ErrorOccurred);
-}
-
-} // namespace rename
-} // namespace clang
diff --git a/clang-rename/USRFindingAction.h b/clang-rename/USRFindingAction.h
deleted file mode 100644
index ac27dad..0000000
--- a/clang-rename/USRFindingAction.h
+++ /dev/null
@@ -1,54 +0,0 @@
-//===--- tools/extra/clang-rename/USRFindingAction.h - Clang rename tool --===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Provides an action to find all relevant USRs at a point.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDING_ACTION_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDING_ACTION_H
-
-#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/ArrayRef.h"
-
-#include <string>
-#include <vector>
-
-namespace clang {
-class ASTConsumer;
-class CompilerInstance;
-class NamedDecl;
-
-namespace rename {
-
-struct USRFindingAction {
-  USRFindingAction(ArrayRef<unsigned> SymbolOffsets,
-                   ArrayRef<std::string> QualifiedNames, bool Force)
-      : SymbolOffsets(SymbolOffsets), QualifiedNames(QualifiedNames),
-        ErrorOccurred(false), Force(Force) {}
-  std::unique_ptr<ASTConsumer> newASTConsumer();
-
-  ArrayRef<std::string> getUSRSpellings() { return SpellingNames; }
-  ArrayRef<std::vector<std::string>> getUSRList() { return USRList; }
-  bool errorOccurred() { return ErrorOccurred; }
-
-private:
-  std::vector<unsigned> SymbolOffsets;
-  std::vector<std::string> QualifiedNames;
-  std::vector<std::string> SpellingNames;
-  std::vector<std::vector<std::string>> USRList;
-  bool ErrorOccurred;
-  bool Force;
-};
-
-} // namespace rename
-} // namespace clang
-
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDING_ACTION_H
diff --git a/clang-rename/USRLocFinder.cpp b/clang-rename/USRLocFinder.cpp
deleted file mode 100644
index 06afb01..0000000
--- a/clang-rename/USRLocFinder.cpp
+++ /dev/null
@@ -1,509 +0,0 @@
-//===--- tools/extra/clang-rename/USRLocFinder.cpp - Clang rename tool ----===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Mehtods for finding all instances of a USR. Our strategy is very
-/// simple; we just compare the USR at every relevant AST node with the one
-/// provided.
-///
-//===----------------------------------------------------------------------===//
-
-#include "USRLocFinder.h"
-#include "USRFinder.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
-#include "clang/Basic/LLVM.h"
-#include "clang/Basic/SourceLocation.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Lex/Lexer.h"
-#include "clang/Tooling/Core/Lookup.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Casting.h"
-#include <cstddef>
-#include <set>
-#include <string>
-#include <vector>
-
-using namespace llvm;
-
-namespace clang {
-namespace rename {
-
-namespace {
-
-// \brief This visitor recursively searches for all instances of a USR in a
-// translation unit and stores them for later usage.
-class USRLocFindingASTVisitor
-    : public clang::RecursiveASTVisitor<USRLocFindingASTVisitor> {
-public:
-  explicit USRLocFindingASTVisitor(const std::vector<std::string> &USRs,
-                                   StringRef PrevName,
-                                   const ASTContext &Context)
-      : USRSet(USRs.begin(), USRs.end()), PrevName(PrevName), Context(Context) {
-  }
-
-  // Declaration visitors:
-
-  bool VisitCXXConstructorDecl(clang::CXXConstructorDecl *ConstructorDecl) {
-    for (const auto *Initializer : ConstructorDecl->inits()) {
-      // Ignore implicit initializers.
-      if (!Initializer->isWritten())
-        continue;
-      if (const clang::FieldDecl *FieldDecl = Initializer->getMember()) {
-        if (USRSet.find(getUSRForDecl(FieldDecl)) != USRSet.end())
-          LocationsFound.push_back(Initializer->getSourceLocation());
-      }
-    }
-    return true;
-  }
-
-  bool VisitNamedDecl(const NamedDecl *Decl) {
-    if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end())
-      checkAndAddLocation(Decl->getLocation());
-    return true;
-  }
-
-  // Expression visitors:
-
-  bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
-    const NamedDecl *Decl = Expr->getFoundDecl();
-
-    if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) {
-      const SourceManager &Manager = Decl->getASTContext().getSourceManager();
-      SourceLocation Location = Manager.getSpellingLoc(Expr->getLocation());
-      checkAndAddLocation(Location);
-    }
-
-    return true;
-  }
-
-  bool VisitMemberExpr(const MemberExpr *Expr) {
-    const NamedDecl *Decl = Expr->getFoundDecl().getDecl();
-    if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) {
-      const SourceManager &Manager = Decl->getASTContext().getSourceManager();
-      SourceLocation Location = Manager.getSpellingLoc(Expr->getMemberLoc());
-      checkAndAddLocation(Location);
-    }
-    return true;
-  }
-
-  // Other visitors:
-
-  bool VisitTypeLoc(const TypeLoc Loc) {
-    if (USRSet.find(getUSRForDecl(Loc.getType()->getAsCXXRecordDecl())) !=
-        USRSet.end())
-      checkAndAddLocation(Loc.getBeginLoc());
-    if (const auto *TemplateTypeParm =
-            dyn_cast<TemplateTypeParmType>(Loc.getType())) {
-      if (USRSet.find(getUSRForDecl(TemplateTypeParm->getDecl())) !=
-          USRSet.end())
-        checkAndAddLocation(Loc.getBeginLoc());
-    }
-    return true;
-  }
-
-  // Non-visitors:
-
-  // \brief Returns a list of unique locations. Duplicate or overlapping
-  // locations are erroneous and should be reported!
-  const std::vector<clang::SourceLocation> &getLocationsFound() const {
-    return LocationsFound;
-  }
-
-  // Namespace traversal:
-  void handleNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) {
-    while (NameLoc) {
-      const NamespaceDecl *Decl =
-          NameLoc.getNestedNameSpecifier()->getAsNamespace();
-      if (Decl && USRSet.find(getUSRForDecl(Decl)) != USRSet.end())
-        checkAndAddLocation(NameLoc.getLocalBeginLoc());
-      NameLoc = NameLoc.getPrefix();
-    }
-  }
-
-private:
-  void checkAndAddLocation(SourceLocation Loc) {
-    const SourceLocation BeginLoc = Loc;
-    const SourceLocation EndLoc = Lexer::getLocForEndOfToken(
-        BeginLoc, 0, Context.getSourceManager(), Context.getLangOpts());
-    StringRef TokenName =
-        Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc, EndLoc),
-                             Context.getSourceManager(), Context.getLangOpts());
-    size_t Offset = TokenName.find(PrevName);
-
-    // The token of the source location we find actually has the old
-    // name.
-    if (Offset != StringRef::npos)
-      LocationsFound.push_back(BeginLoc.getLocWithOffset(Offset));
-  }
-
-  const std::set<std::string> USRSet;
-  const std::string PrevName;
-  std::vector<clang::SourceLocation> LocationsFound;
-  const ASTContext &Context;
-};
-
-SourceLocation StartLocationForType(TypeLoc TL) {
-  // For elaborated types (e.g. `struct a::A`) we want the portion after the
-  // `struct` but including the namespace qualifier, `a::`.
-  if (auto ElaboratedTypeLoc = TL.getAs<clang::ElaboratedTypeLoc>()) {
-    NestedNameSpecifierLoc NestedNameSpecifier =
-        ElaboratedTypeLoc.getQualifierLoc();
-    if (NestedNameSpecifier.getNestedNameSpecifier())
-      return NestedNameSpecifier.getBeginLoc();
-    TL = TL.getNextTypeLoc();
-  }
-  return TL.getLocStart();
-}
-
-SourceLocation EndLocationForType(TypeLoc TL) {
-  // Dig past any namespace or keyword qualifications.
-  while (TL.getTypeLocClass() == TypeLoc::Elaborated ||
-         TL.getTypeLocClass() == TypeLoc::Qualified)
-    TL = TL.getNextTypeLoc();
-
-  // The location for template specializations (e.g. Foo<int>) includes the
-  // templated types in its location range.  We want to restrict this to just
-  // before the `<` character.
-  if (TL.getTypeLocClass() == TypeLoc::TemplateSpecialization) {
-    return TL.castAs<TemplateSpecializationTypeLoc>()
-        .getLAngleLoc()
-        .getLocWithOffset(-1);
-  }
-  return TL.getEndLoc();
-}
-
-NestedNameSpecifier *GetNestedNameForType(TypeLoc TL) {
-  // Dig past any keyword qualifications.
-  while (TL.getTypeLocClass() == TypeLoc::Qualified)
-    TL = TL.getNextTypeLoc();
-
-  // For elaborated types (e.g. `struct a::A`) we want the portion after the
-  // `struct` but including the namespace qualifier, `a::`.
-  if (auto ElaboratedTypeLoc = TL.getAs<clang::ElaboratedTypeLoc>())
-    return ElaboratedTypeLoc.getQualifierLoc().getNestedNameSpecifier();
-  return nullptr;
-}
-
-// Find all locations identified by the given USRs for rename.
-//
-// This class will traverse the AST and find every AST node whose USR is in the
-// given USRs' set.
-class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
-public:
-  RenameLocFinder(llvm::ArrayRef<std::string> USRs, ASTContext &Context)
-      : USRSet(USRs.begin(), USRs.end()), Context(Context) {}
-
-  // A structure records all information of a symbol reference being renamed.
-  // We try to add as few prefix qualifiers as possible.
-  struct RenameInfo {
-    // The begin location of a symbol being renamed.
-    SourceLocation Begin;
-    // The end location of a symbol being renamed.
-    SourceLocation End;
-    // The declaration of a symbol being renamed (can be nullptr).
-    const NamedDecl *FromDecl;
-    // The declaration in which the nested name is contained (can be nullptr).
-    const Decl *Context;
-    // The nested name being replaced (can be nullptr).
-    const NestedNameSpecifier *Specifier;
-  };
-
-  // FIXME: Currently, prefix qualifiers will be added to the renamed symbol
-  // definition (e.g. "class Foo {};" => "class b::Bar {};" when renaming
-  // "a::Foo" to "b::Bar").
-  // For renaming declarations/definitions, prefix qualifiers should be filtered
-  // out.
-  bool VisitNamedDecl(const NamedDecl *Decl) {
-    // UsingDecl has been handled in other place.
-    if (llvm::isa<UsingDecl>(Decl))
-      return true;
-
-    // DestructorDecl has been handled in Typeloc.
-    if (llvm::isa<CXXDestructorDecl>(Decl))
-      return true;
-
-    if (Decl->isImplicit())
-      return true;
-
-    if (isInUSRSet(Decl)) {
-      RenameInfo Info = {Decl->getLocation(), Decl->getLocation(), nullptr,
-                         nullptr, nullptr};
-      RenameInfos.push_back(Info);
-    }
-    return true;
-  }
-
-  bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
-    const NamedDecl *Decl = Expr->getFoundDecl();
-    if (isInUSRSet(Decl)) {
-      RenameInfo Info = {Expr->getSourceRange().getBegin(),
-                         Expr->getSourceRange().getEnd(), Decl,
-                         getClosestAncestorDecl(*Expr), Expr->getQualifier()};
-      RenameInfos.push_back(Info);
-    }
-
-    return true;
-  }
-
-  bool VisitUsingDecl(const UsingDecl *Using) {
-    for (const auto *UsingShadow : Using->shadows()) {
-      if (isInUSRSet(UsingShadow->getTargetDecl())) {
-        UsingDecls.push_back(Using);
-        break;
-      }
-    }
-    return true;
-  }
-
-  bool VisitNestedNameSpecifierLocations(NestedNameSpecifierLoc NestedLoc) {
-    if (!NestedLoc.getNestedNameSpecifier()->getAsType())
-      return true;
-    if (IsTypeAliasWhichWillBeRenamedElsewhere(NestedLoc.getTypeLoc()))
-      return true;
-
-    if (const auto *TargetDecl =
-            getSupportedDeclFromTypeLoc(NestedLoc.getTypeLoc())) {
-      if (isInUSRSet(TargetDecl)) {
-        RenameInfo Info = {NestedLoc.getBeginLoc(),
-                           EndLocationForType(NestedLoc.getTypeLoc()),
-                           TargetDecl, getClosestAncestorDecl(NestedLoc),
-                           NestedLoc.getNestedNameSpecifier()->getPrefix()};
-        RenameInfos.push_back(Info);
-      }
-    }
-    return true;
-  }
-
-  bool VisitTypeLoc(TypeLoc Loc) {
-    if (IsTypeAliasWhichWillBeRenamedElsewhere(Loc))
-      return true;
-
-    auto Parents = Context.getParents(Loc);
-    TypeLoc ParentTypeLoc;
-    if (!Parents.empty()) {
-      // Handle cases of nested name specificier locations.
-      //
-      // The VisitNestedNameSpecifierLoc interface is not impelmented in
-      // RecursiveASTVisitor, we have to handle it explicitly.
-      if (const auto *NSL = Parents[0].get<NestedNameSpecifierLoc>()) {
-        VisitNestedNameSpecifierLocations(*NSL);
-        return true;
-      }
-
-      if (const auto *TL = Parents[0].get<TypeLoc>())
-        ParentTypeLoc = *TL;
-    }
-
-    // Handle the outermost TypeLoc which is directly linked to the interesting
-    // declaration and don't handle nested name specifier locations.
-    if (const auto *TargetDecl = getSupportedDeclFromTypeLoc(Loc)) {
-      if (isInUSRSet(TargetDecl)) {
-        // Only handle the outermost typeLoc.
-        //
-        // For a type like "a::Foo", there will be two typeLocs for it.
-        // One ElaboratedType, the other is RecordType:
-        //
-        //   ElaboratedType 0x33b9390 'a::Foo' sugar
-        //   `-RecordType 0x338fef0 'class a::Foo'
-        //     `-CXXRecord 0x338fe58 'Foo'
-        //
-        // Skip if this is an inner typeLoc.
-        if (!ParentTypeLoc.isNull() &&
-            isInUSRSet(getSupportedDeclFromTypeLoc(ParentTypeLoc)))
-          return true;
-        RenameInfo Info = {StartLocationForType(Loc), EndLocationForType(Loc),
-                           TargetDecl, getClosestAncestorDecl(Loc),
-                           GetNestedNameForType(Loc)};
-        RenameInfos.push_back(Info);
-        return true;
-      }
-    }
-
-    // Handle specific template class specialiation cases.
-    if (const auto *TemplateSpecType =
-            dyn_cast<TemplateSpecializationType>(Loc.getType())) {
-      TypeLoc TargetLoc = Loc;
-      if (!ParentTypeLoc.isNull()) {
-        if (llvm::isa<ElaboratedType>(ParentTypeLoc.getType()))
-          TargetLoc = ParentTypeLoc;
-      }
-
-      if (isInUSRSet(TemplateSpecType->getTemplateName().getAsTemplateDecl())) {
-        TypeLoc TargetLoc = Loc;
-        // FIXME: Find a better way to handle this case.
-        // For the qualified template class specification type like
-        // "ns::Foo<int>" in "ns::Foo<int>& f();", we want the parent typeLoc
-        // (ElaboratedType) of the TemplateSpecializationType in order to
-        // catch the prefix qualifiers "ns::".
-        if (!ParentTypeLoc.isNull() &&
-            llvm::isa<ElaboratedType>(ParentTypeLoc.getType()))
-          TargetLoc = ParentTypeLoc;
-        RenameInfo Info = {
-            StartLocationForType(TargetLoc), EndLocationForType(TargetLoc),
-            TemplateSpecType->getTemplateName().getAsTemplateDecl(),
-            getClosestAncestorDecl(
-                ast_type_traits::DynTypedNode::create(TargetLoc)),
-            GetNestedNameForType(TargetLoc)};
-        RenameInfos.push_back(Info);
-      }
-    }
-    return true;
-  }
-
-  // Returns a list of RenameInfo.
-  const std::vector<RenameInfo> &getRenameInfos() const { return RenameInfos; }
-
-  // Returns a list of using declarations which are needed to update.
-  const std::vector<const UsingDecl *> &getUsingDecls() const {
-    return UsingDecls;
-  }
-
-private:
-  // FIXME: This method may not be suitable for renaming other types like alias
-  // types. Need to figure out a way to handle it.
-  bool IsTypeAliasWhichWillBeRenamedElsewhere(TypeLoc TL) const {
-    while (!TL.isNull()) {
-      // SubstTemplateTypeParm is the TypeLocation class for a substituted type
-      // inside a template expansion so we ignore these.  For example:
-      //
-      // template<typename T> struct S {
-      //   T t;  // <-- this T becomes a TypeLoc(int) with class
-      //         //     SubstTemplateTypeParm when S<int> is instantiated
-      // }
-      if (TL.getTypeLocClass() == TypeLoc::SubstTemplateTypeParm)
-        return true;
-
-      // Typedef is the TypeLocation class for a type which is a typedef to the
-      // type we want to replace.  We ignore the use of the typedef as we will
-      // replace the definition of it.  For example:
-      //
-      // typedef int T;
-      // T a;  // <---  This T is a TypeLoc(int) with class Typedef.
-      if (TL.getTypeLocClass() == TypeLoc::Typedef)
-        return true;
-      TL = TL.getNextTypeLoc();
-    }
-    return false;
-  }
-
-  // Get the supported declaration from a given typeLoc. If the declaration type
-  // is not supported, returns nullptr.
-  //
-  // FIXME: support more types, e.g. enum, type alias.
-  const NamedDecl *getSupportedDeclFromTypeLoc(TypeLoc Loc) {
-    if (const auto *RD = Loc.getType()->getAsCXXRecordDecl())
-      return RD;
-    return nullptr;
-  }
-
-  // Get the closest ancester which is a declaration of a given AST node.
-  template <typename ASTNodeType>
-  const Decl *getClosestAncestorDecl(const ASTNodeType &Node) {
-    auto Parents = Context.getParents(Node);
-    // FIXME: figure out how to handle it when there are multiple parents.
-    if (Parents.size() != 1)
-      return nullptr;
-    if (ast_type_traits::ASTNodeKind::getFromNodeKind<Decl>().isBaseOf(
-            Parents[0].getNodeKind()))
-      return Parents[0].template get<Decl>();
-    return getClosestAncestorDecl(Parents[0]);
-  }
-
-  // Get the parent typeLoc of a given typeLoc. If there is no such parent,
-  // return nullptr.
-  const TypeLoc *getParentTypeLoc(TypeLoc Loc) const {
-    auto Parents = Context.getParents(Loc);
-    // FIXME: figure out how to handle it when there are multiple parents.
-    if (Parents.size() != 1)
-      return nullptr;
-    return Parents[0].get<TypeLoc>();
-  }
-
-  // Check whether the USR of a given Decl is in the USRSet.
-  bool isInUSRSet(const Decl *Decl) const {
-    auto USR = getUSRForDecl(Decl);
-    if (USR.empty())
-      return false;
-    return llvm::is_contained(USRSet, USR);
-  }
-
-  const std::set<std::string> USRSet;
-  ASTContext &Context;
-  std::vector<RenameInfo> RenameInfos;
-  // Record all interested using declarations which contains the using-shadow
-  // declarations of the symbol declarations being renamed.
-  std::vector<const UsingDecl *> UsingDecls;
-};
-
-} // namespace
-
-std::vector<SourceLocation>
-getLocationsOfUSRs(const std::vector<std::string> &USRs, StringRef PrevName,
-                   Decl *Decl) {
-  USRLocFindingASTVisitor Visitor(USRs, PrevName, Decl->getASTContext());
-  Visitor.TraverseDecl(Decl);
-  NestedNameSpecifierLocFinder Finder(Decl->getASTContext());
-
-  for (const auto &Location : Finder.getNestedNameSpecifierLocations())
-    Visitor.handleNestedNameSpecifierLoc(Location);
-
-  return Visitor.getLocationsFound();
-}
-
-std::vector<tooling::AtomicChange>
-createRenameAtomicChanges(llvm::ArrayRef<std::string> USRs,
-                          llvm::StringRef NewName, Decl *TranslationUnitDecl) {
-  RenameLocFinder Finder(USRs, TranslationUnitDecl->getASTContext());
-  Finder.TraverseDecl(TranslationUnitDecl);
-
-  const SourceManager &SM =
-      TranslationUnitDecl->getASTContext().getSourceManager();
-
-  std::vector<tooling::AtomicChange> AtomicChanges;
-  auto Replace = [&](SourceLocation Start, SourceLocation End,
-                     llvm::StringRef Text) {
-    tooling::AtomicChange ReplaceChange = tooling::AtomicChange(SM, Start);
-    llvm::Error Err = ReplaceChange.replace(
-        SM, CharSourceRange::getTokenRange(Start, End), Text);
-    if (Err) {
-      llvm::errs() << "Faile to add replacement to AtomicChange: "
-                   << llvm::toString(std::move(Err)) << "\n";
-      return;
-    }
-    AtomicChanges.push_back(std::move(ReplaceChange));
-  };
-
-  for (const auto &RenameInfo : Finder.getRenameInfos()) {
-    std::string ReplacedName = NewName.str();
-    if (RenameInfo.FromDecl && RenameInfo.Context) {
-      if (!llvm::isa<clang::TranslationUnitDecl>(
-              RenameInfo.Context->getDeclContext())) {
-        ReplacedName = tooling::replaceNestedName(
-            RenameInfo.Specifier, RenameInfo.Context->getDeclContext(),
-            RenameInfo.FromDecl,
-            NewName.startswith("::") ? NewName.str() : ("::" + NewName).str());
-      }
-    }
-    // If the NewName contains leading "::", add it back.
-    if (NewName.startswith("::") && NewName.substr(2) == ReplacedName)
-      ReplacedName = NewName.str();
-    Replace(RenameInfo.Begin, RenameInfo.End, ReplacedName);
-  }
-
-  // Hanlde using declarations explicitly as "using a::Foo" don't trigger
-  // typeLoc for "a::Foo".
-  for (const auto *Using : Finder.getUsingDecls())
-    Replace(Using->getLocStart(), Using->getLocEnd(), "using " + NewName.str());
-
-  return AtomicChanges;
-}
-
-} // namespace rename
-} // namespace clang
diff --git a/clang-rename/USRLocFinder.h b/clang-rename/USRLocFinder.h
deleted file mode 100644
index db4c4a8..0000000
--- a/clang-rename/USRLocFinder.h
+++ /dev/null
@@ -1,49 +0,0 @@
-//===--- tools/extra/clang-rename/USRLocFinder.h - Clang rename tool ------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Provides functionality for finding all instances of a USR in a given
-/// AST.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_LOC_FINDER_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_LOC_FINDER_H
-
-#include "clang/AST/AST.h"
-#include "clang/Tooling/Core/Replacement.h"
-#include "clang/Tooling/Refactoring/AtomicChange.h"
-#include "llvm/ADT/StringRef.h"
-#include <string>
-#include <vector>
-
-namespace clang {
-namespace rename {
-
-/// Create atomic changes for renaming all symbol references which are
-/// identified by the USRs set to a given new name.
-///
-/// \param USRs The set containing USRs of a particular old symbol.
-/// \param NewName The new name to replace old symbol name.
-/// \param TranslationUnitDecl The translation unit declaration.
-///
-/// \return Atomic changes for renaming.
-std::vector<tooling::AtomicChange>
-createRenameAtomicChanges(llvm::ArrayRef<std::string> USRs,
-                          llvm::StringRef NewName, Decl *TranslationUnitDecl);
-
-// FIXME: make this an AST matcher. Wouldn't that be awesome??? I agree!
-std::vector<SourceLocation>
-getLocationsOfUSRs(const std::vector<std::string> &USRs,
-                   llvm::StringRef PrevName, Decl *Decl);
-
-} // namespace rename
-} // namespace clang
-
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_LOC_FINDER_H
diff --git a/clang-rename/tool/CMakeLists.txt b/clang-rename/tool/CMakeLists.txt
deleted file mode 100644
index d2109cd..0000000
--- a/clang-rename/tool/CMakeLists.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-add_clang_executable(clang-rename ClangRename.cpp)
-
-target_link_libraries(clang-rename
-  clangBasic
-  clangFrontend
-  clangRename
-  clangRewrite
-  clangTooling
-  clangToolingCore
-  )
-
-install(TARGETS clang-rename RUNTIME DESTINATION bin)
-
-install(PROGRAMS clang-rename.py
-  DESTINATION share/clang
-  COMPONENT clang-rename)
-install(PROGRAMS clang-rename.el
-  DESTINATION share/clang
-  COMPONENT clang-rename)
diff --git a/clang-rename/tool/ClangRename.cpp b/clang-rename/tool/ClangRename.cpp
deleted file mode 100644
index 82f58e1..0000000
--- a/clang-rename/tool/ClangRename.cpp
+++ /dev/null
@@ -1,240 +0,0 @@
-//===--- tools/extra/clang-rename/ClangRename.cpp - Clang rename tool -----===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief This file implements a clang-rename tool that automatically finds and
-/// renames symbols in C++ code.
-///
-//===----------------------------------------------------------------------===//
-
-#include "../RenamingAction.h"
-#include "../USRFindingAction.h"
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/DiagnosticOptions.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/IdentifierTable.h"
-#include "clang/Basic/LangOptions.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/TokenKinds.h"
-#include "clang/Frontend/TextDiagnosticPrinter.h"
-#include "clang/Rewrite/Core/Rewriter.h"
-#include "clang/Tooling/CommonOptionsParser.h"
-#include "clang/Tooling/Refactoring.h"
-#include "clang/Tooling/ReplacementsYaml.h"
-#include "clang/Tooling/Tooling.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/YAMLTraits.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cstdlib>
-#include <string>
-#include <system_error>
-
-using namespace llvm;
-using namespace clang;
-
-/// \brief An oldname -> newname rename.
-struct RenameAllInfo {
-  unsigned Offset = 0;
-  std::string QualifiedName;
-  std::string NewName;
-};
-
-LLVM_YAML_IS_SEQUENCE_VECTOR(RenameAllInfo)
-
-namespace llvm {
-namespace yaml {
-
-/// \brief Specialized MappingTraits to describe how a RenameAllInfo is
-/// (de)serialized.
-template <> struct MappingTraits<RenameAllInfo> {
-  static void mapping(IO &IO, RenameAllInfo &Info) {
-    IO.mapOptional("Offset", Info.Offset);
-    IO.mapOptional("QualifiedName", Info.QualifiedName);
-    IO.mapRequired("NewName", Info.NewName);
-  }
-};
-
-} // end namespace yaml
-} // end namespace llvm
-
-static cl::OptionCategory ClangRenameOptions("clang-rename common options");
-
-static cl::list<unsigned> SymbolOffsets(
-    "offset",
-    cl::desc("Locates the symbol by offset as opposed to <line>:<column>."),
-    cl::ZeroOrMore, cl::cat(ClangRenameOptions));
-static cl::opt<bool> Inplace("i", cl::desc("Overwrite edited <file>s."),
-                             cl::cat(ClangRenameOptions));
-static cl::list<std::string>
-    QualifiedNames("qualified-name",
-                   cl::desc("The fully qualified name of the symbol."),
-                   cl::ZeroOrMore, cl::cat(ClangRenameOptions));
-
-static cl::list<std::string>
-    NewNames("new-name", cl::desc("The new name to change the symbol to."),
-             cl::ZeroOrMore, cl::cat(ClangRenameOptions));
-static cl::opt<bool> PrintName(
-    "pn",
-    cl::desc("Print the found symbol's name prior to renaming to stderr."),
-    cl::cat(ClangRenameOptions));
-static cl::opt<bool> PrintLocations(
-    "pl", cl::desc("Print the locations affected by renaming to stderr."),
-    cl::cat(ClangRenameOptions));
-static cl::opt<std::string>
-    ExportFixes("export-fixes",
-                cl::desc("YAML file to store suggested fixes in."),
-                cl::value_desc("filename"), cl::cat(ClangRenameOptions));
-static cl::opt<std::string>
-    Input("input", cl::desc("YAML file to load oldname-newname pairs from."),
-          cl::Optional, cl::cat(ClangRenameOptions));
-static cl::opt<bool> Force("force",
-                           cl::desc("Ignore nonexistent qualified names."),
-                           cl::cat(ClangRenameOptions));
-
-int main(int argc, const char **argv) {
-  tooling::CommonOptionsParser OP(argc, argv, ClangRenameOptions);
-
-  if (!Input.empty()) {
-    // Populate QualifiedNames and NewNames from a YAML file.
-    ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =
-        llvm::MemoryBuffer::getFile(Input);
-    if (!Buffer) {
-      errs() << "clang-rename: failed to read " << Input << ": "
-             << Buffer.getError().message() << "\n";
-      return 1;
-    }
-
-    std::vector<RenameAllInfo> Infos;
-    llvm::yaml::Input YAML(Buffer.get()->getBuffer());
-    YAML >> Infos;
-    for (const auto &Info : Infos) {
-      if (!Info.QualifiedName.empty())
-        QualifiedNames.push_back(Info.QualifiedName);
-      else
-        SymbolOffsets.push_back(Info.Offset);
-      NewNames.push_back(Info.NewName);
-    }
-  }
-
-  // Check the arguments for correctness.
-  if (NewNames.empty()) {
-    errs() << "clang-rename: -new-name must be specified.\n\n";
-    exit(1);
-  }
-
-  if (SymbolOffsets.empty() == QualifiedNames.empty()) {
-    errs() << "clang-rename: -offset and -qualified-name can't be present at "
-              "the same time.\n";
-    exit(1);
-  }
-
-  // Check if NewNames is a valid identifier in C++17.
-  LangOptions Options;
-  Options.CPlusPlus = true;
-  Options.CPlusPlus1z = true;
-  IdentifierTable Table(Options);
-  for (const auto &NewName : NewNames) {
-    auto NewNameTokKind = Table.get(NewName).getTokenID();
-    if (!tok::isAnyIdentifier(NewNameTokKind)) {
-      errs() << "ERROR: new name is not a valid identifier in C++17.\n\n";
-      exit(1);
-    }
-  }
-
-  if (SymbolOffsets.size() + QualifiedNames.size() != NewNames.size()) {
-    errs() << "clang-rename: number of symbol offsets(" << SymbolOffsets.size()
-           << ") + number of qualified names (" << QualifiedNames.size()
-           << ") must be equal to number of new names(" << NewNames.size()
-           << ").\n\n";
-    cl::PrintHelpMessage();
-    exit(1);
-  }
-
-  auto Files = OP.getSourcePathList();
-  tooling::RefactoringTool Tool(OP.getCompilations(), Files);
-  rename::USRFindingAction FindingAction(SymbolOffsets, QualifiedNames, Force);
-  Tool.run(tooling::newFrontendActionFactory(&FindingAction).get());
-  const std::vector<std::vector<std::string>> &USRList =
-      FindingAction.getUSRList();
-  const std::vector<std::string> &PrevNames = FindingAction.getUSRSpellings();
-  if (PrintName) {
-    for (const auto &PrevName : PrevNames) {
-      outs() << "clang-rename found name: " << PrevName << '\n';
-    }
-  }
-
-  if (FindingAction.errorOccurred()) {
-    // Diagnostics are already issued at this point.
-    exit(1);
-  }
-
-  if (Force && PrevNames.size() < NewNames.size()) {
-    // No matching PrevName for all NewNames. Without Force this is an error
-    // above already.
-    exit(0);
-  }
-
-  // Perform the renaming.
-  rename::RenamingAction RenameAction(NewNames, PrevNames, USRList,
-                                      Tool.getReplacements(), PrintLocations);
-  std::unique_ptr<tooling::FrontendActionFactory> Factory =
-      tooling::newFrontendActionFactory(&RenameAction);
-  int ExitCode;
-
-  if (Inplace) {
-    ExitCode = Tool.runAndSave(Factory.get());
-  } else {
-    ExitCode = Tool.run(Factory.get());
-
-    if (!ExportFixes.empty()) {
-      std::error_code EC;
-      llvm::raw_fd_ostream OS(ExportFixes, EC, llvm::sys::fs::F_None);
-      if (EC) {
-        llvm::errs() << "Error opening output file: " << EC.message() << '\n';
-        exit(1);
-      }
-
-      // Export replacements.
-      tooling::TranslationUnitReplacements TUR;
-      const auto &FileToReplacements = Tool.getReplacements();
-      for (const auto &Entry : FileToReplacements)
-        TUR.Replacements.insert(TUR.Replacements.end(), Entry.second.begin(),
-                                Entry.second.end());
-
-      yaml::Output YAML(OS);
-      YAML << TUR;
-      OS.close();
-      exit(0);
-    }
-
-    // Write every file to stdout. Right now we just barf the files without any
-    // indication of which files start where, other than that we print the files
-    // in the same order we see them.
-    LangOptions DefaultLangOptions;
-    IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
-    TextDiagnosticPrinter DiagnosticPrinter(errs(), &*DiagOpts);
-    DiagnosticsEngine Diagnostics(
-        IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,
-        &DiagnosticPrinter, false);
-    auto &FileMgr = Tool.getFiles();
-    SourceManager Sources(Diagnostics, FileMgr);
-    Rewriter Rewrite(Sources, DefaultLangOptions);
-
-    Tool.applyAllReplacements(Rewrite);
-    for (const auto &File : Files) {
-      const auto *Entry = FileMgr.getFile(File);
-      const auto ID = Sources.getOrCreateFileID(Entry, SrcMgr::C_User);
-      Rewrite.getEditBuffer(ID).write(outs());
-    }
-  }
-
-  exit(ExitCode);
-}
diff --git a/clang-rename/tool/clang-rename.el b/clang-rename/tool/clang-rename.el
deleted file mode 100644
index b6c3ed4..0000000
--- a/clang-rename/tool/clang-rename.el
+++ /dev/null
@@ -1,79 +0,0 @@
-;;; clang-rename.el --- Renames every occurrence of a symbol found at <offset>.  -*- lexical-binding: t; -*-
-
-;; Keywords: tools, c
-
-;;; Commentary:
-
-;; To install clang-rename.el make sure the directory of this file is in your
-;; `load-path' and add
-;;
-;;   (require 'clang-rename)
-;;
-;; to your .emacs configuration.
-
-;;; Code:
-
-(defgroup clang-rename nil
-  "Integration with clang-rename"
-  :group 'c)
-
-(defcustom clang-rename-binary "clang-rename"
-  "Path to clang-rename executable."
-  :type '(file :must-match t)
-  :group 'clang-rename)
-
-;;;###autoload
-(defun clang-rename (new-name)
-  "Rename all instances of the symbol at point to NEW-NAME using clang-rename."
-  (interactive "sEnter a new name: ")
-  (save-some-buffers :all)
-  ;; clang-rename should not be combined with other operations when undoing.
-  (undo-boundary)
-  (let ((output-buffer (get-buffer-create "*clang-rename*")))
-    (with-current-buffer output-buffer (erase-buffer))
-    (let ((exit-code (call-process
-                      clang-rename-binary nil output-buffer nil
-                      (format "-offset=%d"
-                              ;; clang-rename wants file (byte) offsets, not
-                              ;; buffer (character) positions.
-                              (clang-rename--bufferpos-to-filepos
-                               ;; Emacs treats one character after a symbol as
-                               ;; part of the symbol, but clang-rename doesn’t.
-                               ;; Use the beginning of the current symbol, if
-                               ;; available, to resolve the inconsistency.
-                               (or (car (bounds-of-thing-at-point 'symbol))
-                                   (point))
-                               'exact))
-                      (format "-new-name=%s" new-name)
-                      "-i" (buffer-file-name))))
-      (if (and (integerp exit-code) (zerop exit-code))
-          ;; Success; revert current buffer so it gets the modifications.
-          (progn
-            (kill-buffer output-buffer)
-            (revert-buffer :ignore-auto :noconfirm :preserve-modes))
-        ;; Failure; append exit code to output buffer and display it.
-        (let ((message (clang-rename--format-message
-                        "clang-rename failed with %s %s"
-                        (if (integerp exit-code) "exit status" "signal")
-                        exit-code)))
-          (with-current-buffer output-buffer
-            (insert ?\n message ?\n))
-          (message "%s" message)
-          (display-buffer output-buffer))))))
-
-(defalias 'clang-rename--bufferpos-to-filepos
-  (if (fboundp 'bufferpos-to-filepos)
-      'bufferpos-to-filepos
-    ;; Emacs 24 doesn’t have ‘bufferpos-to-filepos’, simulate it using
-    ;; ‘position-bytes’.
-    (lambda (position &optional _quality _coding-system)
-      (1- (position-bytes position)))))
-
-;; ‘format-message’ is new in Emacs 25.1.  Provide a fallback for older
-;; versions.
-(defalias 'clang-rename--format-message
-  (if (fboundp 'format-message) 'format-message 'format))
-
-(provide 'clang-rename)
-
-;;; clang-rename.el ends here
diff --git a/clang-rename/tool/clang-rename.py b/clang-rename/tool/clang-rename.py
deleted file mode 100644
index 3cc6644..0000000
--- a/clang-rename/tool/clang-rename.py
+++ /dev/null
@@ -1,61 +0,0 @@
-'''
-Minimal clang-rename integration with Vim.
-
-Before installing make sure one of the following is satisfied:
-
-* clang-rename is in your PATH
-* `g:clang_rename_path` in ~/.vimrc points to valid clang-rename executable
-* `binary` in clang-rename.py points to valid to clang-rename executable
-
-To install, simply put this into your ~/.vimrc
-
-    noremap <leader>cr :pyf <path-to>/clang-rename.py<cr>
-
-IMPORTANT NOTE: Before running the tool, make sure you saved the file.
-
-All you have to do now is to place a cursor on a variable/function/class which
-you would like to rename and press '<leader>cr'. You will be prompted for a new
-name if the cursor points to a valid symbol.
-'''
-
-import vim
-import subprocess
-import sys
-
-def main():
-    binary = 'clang-rename'
-    if vim.eval('exists("g:clang_rename_path")') == "1":
-        binary = vim.eval('g:clang_rename_path')
-
-    # Get arguments for clang-rename binary.
-    offset = int(vim.eval('line2byte(line("."))+col(".")')) - 2
-    if offset < 0:
-        print >> sys.stderr, '''Couldn\'t determine cursor position.
-                                Is your file empty?'''
-        return
-    filename = vim.current.buffer.name
-
-    new_name_request_message = 'type new name:'
-    new_name = vim.eval("input('{}\n')".format(new_name_request_message))
-
-    # Call clang-rename.
-    command = [binary,
-               filename,
-               '-i',
-               '-offset', str(offset),
-               '-new-name', str(new_name)]
-    # FIXME: make it possible to run the tool on unsaved file.
-    p = subprocess.Popen(command,
-                         stdout=subprocess.PIPE,
-                         stderr=subprocess.PIPE)
-    stdout, stderr = p.communicate()
-
-    if stderr:
-        print stderr
-
-    # Reload all buffers in Vim.
-    vim.command("checktime")
-
-
-if __name__ == '__main__':
-    main()
diff --git a/clang-reorder-fields/ReorderFieldsAction.cpp b/clang-reorder-fields/ReorderFieldsAction.cpp
index 1996380..7cb8abe 100644
--- a/clang-reorder-fields/ReorderFieldsAction.cpp
+++ b/clang-reorder-fields/ReorderFieldsAction.cpp
@@ -22,21 +22,23 @@
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/Lex/Lexer.h"
 #include "clang/Tooling/Refactoring.h"
+#include "llvm/ADT/SetVector.h"
 #include <algorithm>
 #include <string>
 
 namespace clang {
 namespace reorder_fields {
 using namespace clang::ast_matchers;
+using llvm::SmallSetVector;
 
 /// \brief Finds the definition of a record by name.
 ///
 /// \returns nullptr if the name is ambiguous or not found.
-static const CXXRecordDecl *findDefinition(StringRef RecordName,
-                                           ASTContext &Context) {
-  auto Results = match(
-      recordDecl(hasName(RecordName), isDefinition()).bind("cxxRecordDecl"),
-      Context);
+static const RecordDecl *findDefinition(StringRef RecordName,
+                                        ASTContext &Context) {
+  auto Results =
+      match(recordDecl(hasName(RecordName), isDefinition()).bind("recordDecl"),
+            Context);
   if (Results.empty()) {
     llvm::errs() << "Definition of " << RecordName << "  not found\n";
     return nullptr;
@@ -46,14 +48,14 @@
                  << " is ambiguous, several definitions found\n";
     return nullptr;
   }
-  return selectFirst<CXXRecordDecl>("cxxRecordDecl", Results);
+  return selectFirst<RecordDecl>("recordDecl", Results);
 }
 
 /// \brief Calculates the new order of fields.
 ///
 /// \returns empty vector if the list of fields doesn't match the definition.
 static SmallVector<unsigned, 4>
-getNewFieldsOrder(const CXXRecordDecl *Definition,
+getNewFieldsOrder(const RecordDecl *Definition,
                   ArrayRef<std::string> DesiredFieldsOrder) {
   assert(Definition && "Definition is null");
 
@@ -91,13 +93,35 @@
   consumeError(Replacements[R.getFilePath()].add(R));
 }
 
+/// \brief Find all member fields used in the given init-list initializer expr
+/// that belong to the same record
+///
+/// \returns a set of field declarations, empty if none were present
+static SmallSetVector<FieldDecl *, 1>
+findMembersUsedInInitExpr(const CXXCtorInitializer *Initializer,
+                          ASTContext &Context) {
+  SmallSetVector<FieldDecl *, 1> Results;
+  // Note that this does not pick up member fields of base classes since
+  // for those accesses Sema::PerformObjectMemberConversion always inserts an
+  // UncheckedDerivedToBase ImplicitCastExpr between the this expr and the
+  // object expression
+  auto FoundExprs =
+      match(findAll(memberExpr(hasObjectExpression(cxxThisExpr())).bind("ME")),
+            *Initializer->getInit(), Context);
+  for (BoundNodes &BN : FoundExprs)
+    if (auto *MemExpr = BN.getNodeAs<MemberExpr>("ME"))
+      if (auto *FD = dyn_cast<FieldDecl>(MemExpr->getMemberDecl()))
+        Results.insert(FD);
+  return Results;
+}
+
 /// \brief Reorders fields in the definition of a struct/class.
 ///
 /// At the moment reodering of fields with
 /// different accesses (public/protected/private) is not supported.
 /// \returns true on success.
 static bool reorderFieldsInDefinition(
-    const CXXRecordDecl *Definition, ArrayRef<unsigned> NewFieldsOrder,
+    const RecordDecl *Definition, ArrayRef<unsigned> NewFieldsOrder,
     const ASTContext &Context,
     std::map<std::string, tooling::Replacements> &Replacements) {
   assert(Definition && "Definition is null");
@@ -129,11 +153,12 @@
 
 /// \brief Reorders initializers in a C++ struct/class constructor.
 ///
-/// A constructor can have initializers for an arbitrary subset of the class's fields.
-/// Thus, we need to ensure that we reorder just the initializers that are present.
+/// A constructor can have initializers for an arbitrary subset of the class's
+/// fields. Thus, we need to ensure that we reorder just the initializers that
+/// are present.
 static void reorderFieldsInConstructor(
     const CXXConstructorDecl *CtorDecl, ArrayRef<unsigned> NewFieldsOrder,
-    const ASTContext &Context,
+    ASTContext &Context,
     std::map<std::string, tooling::Replacements> &Replacements) {
   assert(CtorDecl && "Constructor declaration is null");
   if (CtorDecl->isImplicit() || CtorDecl->getNumCtorInitializers() <= 1)
@@ -151,8 +176,26 @@
   SmallVector<const CXXCtorInitializer *, 10> OldWrittenInitializersOrder;
   SmallVector<const CXXCtorInitializer *, 10> NewWrittenInitializersOrder;
   for (const auto *Initializer : CtorDecl->inits()) {
-    if (!Initializer->isWritten())
+    if (!Initializer->isMemberInitializer() || !Initializer->isWritten())
       continue;
+
+    // Warn if this reordering violates initialization expr dependencies.
+    const FieldDecl *ThisM = Initializer->getMember();
+    const auto UsedMembers = findMembersUsedInInitExpr(Initializer, Context);
+    for (const FieldDecl *UM : UsedMembers) {
+      if (NewFieldsPositions[UM->getFieldIndex()] >
+          NewFieldsPositions[ThisM->getFieldIndex()]) {
+        DiagnosticsEngine &DiagEngine = Context.getDiagnostics();
+        auto Description = ("reordering field " + UM->getName() + " after " +
+                            ThisM->getName() + " makes " + UM->getName() +
+                            " uninitialized when used in init expression")
+                               .str();
+        unsigned ID = DiagEngine.getDiagnosticIDs()->getCustomDiagID(
+            DiagnosticIDs::Warning, Description);
+        DiagEngine.Report(Initializer->getSourceLocation(), ID);
+      }
+    }
+
     OldWrittenInitializersOrder.push_back(Initializer);
     NewWrittenInitializersOrder.push_back(Initializer);
   }
@@ -182,12 +225,12 @@
     const ASTContext &Context,
     std::map<std::string, tooling::Replacements> &Replacements) {
   assert(InitListEx && "Init list expression is null");
-  // We care only about InitListExprs which originate from source code. 
+  // We care only about InitListExprs which originate from source code.
   // Implicit InitListExprs are created by the semantic analyzer.
   if (!InitListEx->isExplicit())
     return true;
-  // The method InitListExpr::getSyntacticForm may return nullptr indicating that
-  // the current initializer list also serves as its syntactic form.
+  // The method InitListExpr::getSyntacticForm may return nullptr indicating
+  // that the current initializer list also serves as its syntactic form.
   if (const auto *SyntacticForm = InitListEx->getSyntacticForm())
     InitListEx = SyntacticForm;
   // If there are no initializers we do not need to change anything.
@@ -199,10 +242,9 @@
   }
   for (unsigned i = 0, e = InitListEx->getNumInits(); i < e; ++i)
     if (i != NewFieldsOrder[i])
-      addReplacement(
-          InitListEx->getInit(i)->getSourceRange(),
-          InitListEx->getInit(NewFieldsOrder[i])->getSourceRange(), Context,
-          Replacements);
+      addReplacement(InitListEx->getInit(i)->getSourceRange(),
+                     InitListEx->getInit(NewFieldsOrder[i])->getSourceRange(),
+                     Context, Replacements);
   return true;
 }
 
@@ -223,7 +265,7 @@
   ReorderingConsumer &operator=(const ReorderingConsumer &) = delete;
 
   void HandleTranslationUnit(ASTContext &Context) override {
-    const CXXRecordDecl *RD = findDefinition(RecordName, Context);
+    const RecordDecl *RD = findDefinition(RecordName, Context);
     if (!RD)
       return;
     SmallVector<unsigned, 4> NewFieldsOrder =
@@ -232,16 +274,21 @@
       return;
     if (!reorderFieldsInDefinition(RD, NewFieldsOrder, Context, Replacements))
       return;
-    for (const auto *C : RD->ctors())
-      if (const auto *D = dyn_cast<CXXConstructorDecl>(C->getDefinition()))
-        reorderFieldsInConstructor(cast<const CXXConstructorDecl>(D),
-                                   NewFieldsOrder, Context, Replacements);
 
-    // We only need to reorder init list expressions for aggregate types.
+    // CXXRD will be nullptr if C code (not C++) is being processed.
+    const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD);
+    if (CXXRD)
+      for (const auto *C : CXXRD->ctors())
+        if (const auto *D = dyn_cast<CXXConstructorDecl>(C->getDefinition()))
+          reorderFieldsInConstructor(cast<const CXXConstructorDecl>(D),
+                                     NewFieldsOrder, Context, Replacements);
+
+    // We only need to reorder init list expressions for
+    // plain C structs or C++ aggregate types.
     // For other types the order of constructor parameters is used,
     // which we don't change at the moment.
     // Now (v0) partial initialization is not supported.
-    if (RD->isAggregate())
+    if (!CXXRD || CXXRD->isAggregate())
       for (auto Result :
            match(initListExpr(hasType(equalsNode(RD))).bind("initListExpr"),
                  Context))
diff --git a/clang-tidy/CMakeLists.txt b/clang-tidy/CMakeLists.txt
index 2de309d..9d6fc7f 100644
--- a/clang-tidy/CMakeLists.txt
+++ b/clang-tidy/CMakeLists.txt
@@ -26,7 +26,9 @@
   clangToolingCore
   )
 
+add_subdirectory(android)
 add_subdirectory(boost)
+add_subdirectory(bugprone)
 add_subdirectory(cert)
 add_subdirectory(cppcoreguidelines)
 add_subdirectory(google)
diff --git a/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tidy/ClangTidyDiagnosticConsumer.cpp
index 6bbb9bc..44f78b8 100644
--- a/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ b/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -36,10 +36,9 @@
       : DiagnosticRenderer(LangOpts, DiagOpts), Error(Error) {}
 
 protected:
-  void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc,
+  void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
                              DiagnosticsEngine::Level Level, StringRef Message,
                              ArrayRef<CharSourceRange> Ranges,
-                             const SourceManager *SM,
                              DiagOrStoredDiag Info) override {
     // Remove check name from the message.
     // FIXME: Remove this once there's a better way to pass check names than
@@ -49,9 +48,10 @@
     if (Message.endswith(CheckNameInMessage))
       Message = Message.substr(0, Message.size() - CheckNameInMessage.size());
 
-    auto TidyMessage = Loc.isValid()
-                           ? tooling::DiagnosticMessage(Message, *SM, Loc)
-                           : tooling::DiagnosticMessage(Message);
+    auto TidyMessage =
+        Loc.isValid()
+            ? tooling::DiagnosticMessage(Message, Loc.getManager(), Loc)
+            : tooling::DiagnosticMessage(Message);
     if (Level == DiagnosticsEngine::Note) {
       Error.Notes.push_back(TidyMessage);
       return;
@@ -60,15 +60,13 @@
     Error.Message = TidyMessage;
   }
 
-  void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
+  void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
                          DiagnosticsEngine::Level Level,
-                         ArrayRef<CharSourceRange> Ranges,
-                         const SourceManager &SM) override {}
+                         ArrayRef<CharSourceRange> Ranges) override {}
 
-  void emitCodeContext(SourceLocation Loc, DiagnosticsEngine::Level Level,
+  void emitCodeContext(FullSourceLoc Loc, DiagnosticsEngine::Level Level,
                        SmallVectorImpl<CharSourceRange> &Ranges,
-                       ArrayRef<FixItHint> Hints,
-                       const SourceManager &SM) override {
+                       ArrayRef<FixItHint> Hints) override {
     assert(Loc.isValid());
     for (const auto &FixIt : Hints) {
       CharSourceRange Range = FixIt.RemoveRange;
@@ -77,7 +75,8 @@
       assert(Range.getBegin().isFileID() && Range.getEnd().isFileID() &&
              "Only file locations supported in fix-it hints.");
 
-      tooling::Replacement Replacement(SM, Range, FixIt.CodeToInsert);
+      tooling::Replacement Replacement(Loc.getManager(), Range,
+                                       FixIt.CodeToInsert);
       llvm::Error Err = Error.Fix[Replacement.getFilePath()].add(Replacement);
       // FIXME: better error handling (at least, don't let other replacements be
       // applied).
@@ -89,16 +88,13 @@
     }
   }
 
-  void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
-                           const SourceManager &SM) override {}
+  void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) override {}
 
-  void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
-                          StringRef ModuleName,
-                          const SourceManager &SM) override {}
+  void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc,
+                          StringRef ModuleName) override {}
 
-  void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
-                                  StringRef ModuleName,
-                                  const SourceManager &SM) override {}
+  void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc,
+                                  StringRef ModuleName) override {}
 
   void endDiagnostic(DiagOrStoredDiag D,
                      DiagnosticsEngine::Level Level) override {
@@ -119,7 +115,7 @@
 // Returns true if GlobList starts with the negative indicator ('-'), removes it
 // from the GlobList.
 static bool ConsumeNegativeIndicator(StringRef &GlobList) {
-  GlobList = GlobList.trim(' ');
+  GlobList = GlobList.trim(" \r\n");
   if (GlobList.startswith("-")) {
     GlobList = GlobList.substr(1);
     return true;
@@ -419,11 +415,12 @@
       Errors.back());
   SmallString<100> Message;
   Info.FormatDiagnostic(Message);
-  SourceManager *Sources = nullptr;
-  if (Info.hasSourceManager())
-    Sources = &Info.getSourceManager();
-  Converter.emitDiagnostic(Info.getLocation(), DiagLevel, Message,
-                           Info.getRanges(), Info.getFixItHints(), Sources);
+  FullSourceLoc Loc =
+      (Info.getLocation().isInvalid())
+          ? FullSourceLoc()
+          : FullSourceLoc(Info.getLocation(), Info.getSourceManager());
+  Converter.emitDiagnostic(Loc, DiagLevel, Message, Info.getRanges(),
+                           Info.getFixItHints());
 
   checkFilters(Info.getLocation());
 }
diff --git a/clang-tidy/ClangTidyOptions.cpp b/clang-tidy/ClangTidyOptions.cpp
index 83f57e5..7cbe6ac 100644
--- a/clang-tidy/ClangTidyOptions.cpp
+++ b/clang-tidy/ClangTidyOptions.cpp
@@ -27,8 +27,6 @@
 
 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FileFilter)
 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FileFilter::LineRange)
-LLVM_YAML_IS_SEQUENCE_VECTOR(ClangTidyOptions::StringPair)
-LLVM_YAML_IS_SEQUENCE_VECTOR(std::string)
 
 namespace llvm {
 namespace yaml {
diff --git a/clang-tidy/add_new_check.py b/clang-tidy/add_new_check.py
index 7032ad9..c7d212e 100755
--- a/clang-tidy/add_new_check.py
+++ b/clang-tidy/add_new_check.py
@@ -189,6 +189,37 @@
       f.write(line)
 
 
+# Adds a release notes entry.
+def add_release_notes(module_path, module, check_name):
+  check_name_dashes = module + '-' + check_name
+  filename = os.path.normpath(os.path.join(module_path,
+                                           '../../docs/ReleaseNotes.rst'))
+  with open(filename, 'r') as f:
+    lines = f.readlines()
+
+  print('Updating %s...' % filename)
+  with open(filename, 'wb') as f:
+    note_added = False
+    header_found = False
+
+    for line in lines:
+      if not note_added:
+        match = re.search('Improvements to clang-tidy', line)
+        if match:
+          header_found = True
+        elif header_found:
+          if not line.startswith('----'):
+            f.write("""
+- New `%s
+  <http://clang.llvm.org/extra/clang-tidy/checks/%s.html>`_ check
+
+  FIXME: add release notes.
+""" % (check_name_dashes, check_name_dashes))
+            note_added = True
+
+      f.write(line)
+
+
 # Adds a test for the check.
 def write_test(module_path, module, check_name):
   check_name_dashes = module + '-' + check_name
@@ -300,6 +331,7 @@
   write_header(module_path, module, check_name, check_name_camel)
   write_implementation(module_path, module, check_name_camel)
   adapt_module(module_path, module, check_name, check_name_camel)
+  add_release_notes(module_path, module, check_name)
   write_test(module_path, module, check_name)
   write_docs(module_path, module, check_name)
   update_checks_list(clang_tidy_path)
diff --git a/clang-tidy/android/AndroidTidyModule.cpp b/clang-tidy/android/AndroidTidyModule.cpp
new file mode 100644
index 0000000..aec1007
--- /dev/null
+++ b/clang-tidy/android/AndroidTidyModule.cpp
@@ -0,0 +1,67 @@
+//===--- AndroidTidyModule.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 "../ClangTidy.h"
+#include "../ClangTidyModule.h"
+#include "../ClangTidyModuleRegistry.h"
+#include "CloexecAccept4Check.h"
+#include "CloexecAcceptCheck.h"
+#include "CloexecCreatCheck.h"
+#include "CloexecEpollCreate1Check.h"
+#include "CloexecEpollCreateCheck.h"
+#include "CloexecDupCheck.h"
+#include "CloexecFopenCheck.h"
+#include "CloexecInotifyInit1Check.h"
+#include "CloexecInotifyInitCheck.h"
+#include "CloexecMemfdCreateCheck.h"
+#include "CloexecOpenCheck.h"
+#include "CloexecSocketCheck.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+/// This module is for Android specific checks.
+class AndroidModule : public ClangTidyModule {
+public:
+  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<CloexecAccept4Check>("android-cloexec-accept4");
+    CheckFactories.registerCheck<CloexecAcceptCheck>("android-cloexec-accept");
+    CheckFactories.registerCheck<CloexecCreatCheck>("android-cloexec-creat");
+    CheckFactories.registerCheck<CloexecEpollCreate1Check>(
+        "android-cloexec-epoll-create1");
+    CheckFactories.registerCheck<CloexecEpollCreateCheck>(
+        "android-cloexec-epoll-create");
+    CheckFactories.registerCheck<CloexecDupCheck>("android-cloexec-dup");
+    CheckFactories.registerCheck<CloexecFopenCheck>("android-cloexec-fopen");
+    CheckFactories.registerCheck<CloexecInotifyInitCheck>(
+        "android-cloexec-inotify-init");
+    CheckFactories.registerCheck<CloexecInotifyInit1Check>(
+        "android-cloexec-inotify-init1");
+    CheckFactories.registerCheck<CloexecMemfdCreateCheck>(
+        "android-cloexec-memfd-create");
+    CheckFactories.registerCheck<CloexecOpenCheck>("android-cloexec-open");
+    CheckFactories.registerCheck<CloexecSocketCheck>("android-cloexec-socket");
+  }
+};
+
+// Register the AndroidTidyModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add<AndroidModule>
+    X("android-module", "Adds Android platform checks.");
+
+} // namespace android
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the AndroidModule.
+volatile int AndroidModuleAnchorSource = 0;
+
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/android/CMakeLists.txt b/clang-tidy/android/CMakeLists.txt
new file mode 100644
index 0000000..6b2d452
--- /dev/null
+++ b/clang-tidy/android/CMakeLists.txt
@@ -0,0 +1,26 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangTidyAndroidModule
+  AndroidTidyModule.cpp
+  CloexecAccept4Check.cpp
+  CloexecAcceptCheck.cpp
+  CloexecCheck.cpp
+  CloexecCreatCheck.cpp
+  CloexecEpollCreate1Check.cpp
+  CloexecEpollCreateCheck.cpp
+  CloexecDupCheck.cpp
+  CloexecFopenCheck.cpp
+  CloexecInotifyInit1Check.cpp
+  CloexecInotifyInitCheck.cpp
+  CloexecMemfdCreateCheck.cpp
+  CloexecOpenCheck.cpp
+  CloexecSocketCheck.cpp
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangLex
+  clangTidy
+  clangTidyUtils
+  )
diff --git a/clang-tidy/android/CloexecAccept4Check.cpp b/clang-tidy/android/CloexecAccept4Check.cpp
new file mode 100644
index 0000000..a86eedd
--- /dev/null
+++ b/clang-tidy/android/CloexecAccept4Check.cpp
@@ -0,0 +1,40 @@
+//===--- CloexecAccept4Check.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 "CloexecAccept4Check.h"
+#include "../utils/ASTUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+void CloexecAccept4Check::registerMatchers(MatchFinder *Finder) {
+  auto SockAddrPointerType =
+      hasType(pointsTo(recordDecl(isStruct(), hasName("sockaddr"))));
+  auto SockLenPointerType = hasType(pointsTo(namedDecl(hasName("socklen_t"))));
+
+  registerMatchersImpl(Finder,
+                       functionDecl(returns(isInteger()), hasName("accept4"),
+                                    hasParameter(0, hasType(isInteger())),
+                                    hasParameter(1, SockAddrPointerType),
+                                    hasParameter(2, SockLenPointerType),
+                                    hasParameter(3, hasType(isInteger()))));
+}
+
+void CloexecAccept4Check::check(const MatchFinder::MatchResult &Result) {
+  insertMacroFlag(Result, /*MarcoFlag=*/"SOCK_CLOEXEC", /*ArgPos=*/3);
+}
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/android/CloexecAccept4Check.h b/clang-tidy/android/CloexecAccept4Check.h
new file mode 100644
index 0000000..0cf3215
--- /dev/null
+++ b/clang-tidy/android/CloexecAccept4Check.h
@@ -0,0 +1,35 @@
+//===--- CloexecAccept4Check.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_ANDROID_CLOEXEC_ACCEPT4_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_ACCEPT4_H
+
+#include "CloexecCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+/// Finds code that uses accept4() without using the SOCK_CLOEXEC flag.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-accept4.html
+class CloexecAccept4Check : public CloexecCheck {
+public:
+  CloexecAccept4Check(StringRef Name, ClangTidyContext *Context)
+      : CloexecCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_ACCEPT4_H
diff --git a/clang-tidy/android/CloexecAcceptCheck.cpp b/clang-tidy/android/CloexecAcceptCheck.cpp
new file mode 100644
index 0000000..f583bd0
--- /dev/null
+++ b/clang-tidy/android/CloexecAcceptCheck.cpp
@@ -0,0 +1,47 @@
+//===--- CloexecAcceptCheck.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 "CloexecAcceptCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+void CloexecAcceptCheck::registerMatchers(MatchFinder *Finder) {
+  auto SockAddrPointerType =
+      hasType(pointsTo(recordDecl(isStruct(), hasName("sockaddr"))));
+  auto SockLenPointerType = hasType(pointsTo(namedDecl(hasName("socklen_t"))));
+
+  registerMatchersImpl(Finder,
+                       functionDecl(returns(isInteger()), hasName("accept"),
+                                    hasParameter(0, hasType(isInteger())),
+                                    hasParameter(1, SockAddrPointerType),
+                                    hasParameter(2, SockLenPointerType)));
+}
+
+void CloexecAcceptCheck::check(const MatchFinder::MatchResult &Result) {
+  const std::string &ReplacementText =
+      (Twine("accept4(") + getSpellingArg(Result, 0) + ", " +
+       getSpellingArg(Result, 1) + ", " + getSpellingArg(Result, 2) +
+       ", SOCK_CLOEXEC)")
+          .str();
+
+  replaceFunc(
+      Result,
+      "prefer accept4() to accept() because accept4() allows SOCK_CLOEXEC",
+      ReplacementText);
+}
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/android/CloexecAcceptCheck.h b/clang-tidy/android/CloexecAcceptCheck.h
new file mode 100644
index 0000000..cba1c09
--- /dev/null
+++ b/clang-tidy/android/CloexecAcceptCheck.h
@@ -0,0 +1,35 @@
+//===--- CloexecAcceptCheck.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_ANDROID_CLOEXEC_ACCEPT_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_ACCEPT_H
+
+#include "CloexecCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+/// accept() is better to be replaced by accept4().
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-accept.html
+class CloexecAcceptCheck : public CloexecCheck {
+public:
+  CloexecAcceptCheck(StringRef Name, ClangTidyContext *Context)
+      : CloexecCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_ACCEPT_H
diff --git a/clang-tidy/android/CloexecCheck.cpp b/clang-tidy/android/CloexecCheck.cpp
new file mode 100644
index 0000000..8473f1a
--- /dev/null
+++ b/clang-tidy/android/CloexecCheck.cpp
@@ -0,0 +1,114 @@
+//===--- CloexecCheck.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 "CloexecCheck.h"
+#include "../utils/ASTUtils.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 android {
+
+namespace {
+// Helper function to form the correct string mode for Type3.
+// Build the replace text. If it's string constant, add <Mode> directly in the
+// end of the string. Else, add <Mode>.
+std::string buildFixMsgForStringFlag(const Expr *Arg, const SourceManager &SM,
+                                     const LangOptions &LangOpts, char Mode) {
+  if (Arg->getLocStart().isMacroID())
+    return (Lexer::getSourceText(
+                CharSourceRange::getTokenRange(Arg->getSourceRange()), SM,
+                LangOpts) +
+            " \"" + Twine(Mode) + "\"")
+        .str();
+
+  StringRef SR = cast<StringLiteral>(Arg->IgnoreParenCasts())->getString();
+  return ("\"" + SR + Twine(Mode) + "\"").str();
+}
+} // namespace
+
+const char *CloexecCheck::FuncDeclBindingStr = "funcDecl";
+
+const char *CloexecCheck::FuncBindingStr ="func";
+
+void CloexecCheck::registerMatchersImpl(
+    MatchFinder *Finder, internal::Matcher<FunctionDecl> Function) {
+  // We assume all the checked APIs are C functions.
+  Finder->addMatcher(
+      callExpr(
+          callee(functionDecl(isExternC(), Function).bind(FuncDeclBindingStr)))
+          .bind(FuncBindingStr),
+      this);
+}
+
+void CloexecCheck::insertMacroFlag(const MatchFinder::MatchResult &Result,
+                                   StringRef MacroFlag, int ArgPos) {
+  const auto *MatchedCall = Result.Nodes.getNodeAs<CallExpr>(FuncBindingStr);
+  const auto *FlagArg = MatchedCall->getArg(ArgPos);
+  const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>(FuncDeclBindingStr);
+  SourceManager &SM = *Result.SourceManager;
+
+  if (utils::exprHasBitFlagWithSpelling(FlagArg->IgnoreParenCasts(), SM,
+                                        Result.Context->getLangOpts(),
+                                        MacroFlag))
+    return;
+
+  SourceLocation EndLoc =
+      Lexer::getLocForEndOfToken(SM.getFileLoc(FlagArg->getLocEnd()), 0, SM,
+                                 Result.Context->getLangOpts());
+
+  diag(EndLoc, "%0 should use %1 where possible")
+      << FD << MacroFlag
+      << FixItHint::CreateInsertion(EndLoc, (Twine(" | ") + MacroFlag).str());
+}
+
+void CloexecCheck::replaceFunc(const MatchFinder::MatchResult &Result,
+                               StringRef WarningMsg, StringRef FixMsg) {
+  const auto *MatchedCall = Result.Nodes.getNodeAs<CallExpr>(FuncBindingStr);
+  diag(MatchedCall->getLocStart(), WarningMsg)
+      << FixItHint::CreateReplacement(MatchedCall->getSourceRange(), FixMsg);
+}
+
+void CloexecCheck::insertStringFlag(
+    const ast_matchers::MatchFinder::MatchResult &Result, const char Mode,
+    const int ArgPos) {
+  const auto *MatchedCall = Result.Nodes.getNodeAs<CallExpr>(FuncBindingStr);
+  const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>(FuncDeclBindingStr);
+  const auto *ModeArg = MatchedCall->getArg(ArgPos);
+
+  // Check if the <Mode> may be in the mode string.
+  const auto *ModeStr = dyn_cast<StringLiteral>(ModeArg->IgnoreParenCasts());
+  if (!ModeStr || (ModeStr->getString().find(Mode) != StringRef::npos))
+    return;
+
+  const std::string &ReplacementText = buildFixMsgForStringFlag(
+      ModeArg, *Result.SourceManager, Result.Context->getLangOpts(), Mode);
+
+  diag(ModeArg->getLocStart(), "use %0 mode '%1' to set O_CLOEXEC")
+      << FD << std::string(1, Mode)
+      << FixItHint::CreateReplacement(ModeArg->getSourceRange(),
+                                      ReplacementText);
+}
+
+StringRef CloexecCheck::getSpellingArg(const MatchFinder::MatchResult &Result,
+                                       int N) const {
+  const auto *MatchedCall = Result.Nodes.getNodeAs<CallExpr>(FuncBindingStr);
+  const SourceManager &SM = *Result.SourceManager;
+  return Lexer::getSourceText(
+      CharSourceRange::getTokenRange(MatchedCall->getArg(N)->getSourceRange()),
+      SM, Result.Context->getLangOpts());
+}
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/android/CloexecCheck.h b/clang-tidy/android/CloexecCheck.h
new file mode 100644
index 0000000..1c58a31
--- /dev/null
+++ b/clang-tidy/android/CloexecCheck.h
@@ -0,0 +1,105 @@
+//===--- CloexecCheck.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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the declaration of the CloexecCheck class, which is the
+/// base class for all of the close-on-exec checks in Android module.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+/// \brief The base class for all close-on-exec checks in Android module.
+/// To be specific, there are some functions that need the close-on-exec flag to
+/// prevent the file descriptor leakage on fork+exec and this class provides
+/// utilities to identify and fix these C functions.
+class CloexecCheck : public ClangTidyCheck {
+public:
+  CloexecCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+
+protected:
+  void
+  registerMatchersImpl(ast_matchers::MatchFinder *Finder,
+                       ast_matchers::internal::Matcher<FunctionDecl> Function);
+
+  /// Currently, we have three types of fixes.
+  ///
+  /// Type1 is to insert the necessary macro flag in the flag argument. For
+  /// example, 'O_CLOEXEC' is required in function 'open()', so
+  /// \code
+  ///   open(file, O_RDONLY);
+  /// \endcode
+  /// should be
+  /// \code
+  ///   open(file, O_RDONLY | O_CLOEXE);
+  /// \endcode
+  ///
+  /// \param [out] Result MatchResult from AST matcher.
+  /// \param MacroFlag The macro name of the flag.
+  /// \param ArgPos The 0-based position of the flag argument.
+  void insertMacroFlag(const ast_matchers::MatchFinder::MatchResult &Result,
+                       StringRef MacroFlag, int ArgPos);
+
+  /// Type2 is to replace the API to another function that has required the
+  /// ability. For example:
+  /// \code
+  ///   creat(path, mode);
+  /// \endcode
+  /// should be
+  /// \code
+  ///   open(path, O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, mode)
+  /// \endcode
+  ///
+  /// \param [out] Result MatchResult from AST matcher.
+  /// \param WarningMsg The warning message.
+  /// \param FixMsg The fix message.
+  void replaceFunc(const ast_matchers::MatchFinder::MatchResult &Result,
+                   StringRef WarningMsg, StringRef FixMsg);
+
+  /// Type3 is also to add a flag to the corresponding argument, but this time,
+  /// the flag is some string and each char represents a mode rather than a
+  /// macro. For example, 'fopen' needs char 'e' in its mode argument string, so
+  /// \code
+  ///   fopen(in_file, "r");
+  /// \endcode
+  /// should be
+  /// \code
+  ///   fopen(in_file, "re");
+  /// \endcode
+  ///
+  /// \param [out] Result MatchResult from AST matcher.
+  /// \param Mode The required mode char.
+  /// \param ArgPos The 0-based position of the flag argument.
+  void insertStringFlag(const ast_matchers::MatchFinder::MatchResult &Result,
+                        const char Mode, const int ArgPos);
+
+  /// Helper function to get the spelling of a particular argument.
+  StringRef getSpellingArg(const ast_matchers::MatchFinder::MatchResult &Result,
+                           int N) const;
+
+  /// Binding name of the FuncDecl of a function call.
+  static const char *FuncDeclBindingStr;
+
+  /// Binding name of the function call expression.
+  static const char *FuncBindingStr;
+};
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_H
diff --git a/clang-tidy/android/CloexecCreatCheck.cpp b/clang-tidy/android/CloexecCreatCheck.cpp
new file mode 100644
index 0000000..83ca49a
--- /dev/null
+++ b/clang-tidy/android/CloexecCreatCheck.cpp
@@ -0,0 +1,43 @@
+//===--- CloexecCreatCheck.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 "CloexecCreatCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+void CloexecCreatCheck::registerMatchers(MatchFinder *Finder) {
+  auto CharPointerType = hasType(pointerType(pointee(isAnyCharacter())));
+  auto MODETType = hasType(namedDecl(hasName("mode_t")));
+  registerMatchersImpl(Finder,
+                       functionDecl(isExternC(), returns(isInteger()),
+                                    hasName("creat"),
+                                    hasParameter(0, CharPointerType),
+                                    hasParameter(1, MODETType)));
+}
+
+void CloexecCreatCheck::check(const MatchFinder::MatchResult &Result) {
+  const std::string &ReplacementText =
+      (Twine("open (") + getSpellingArg(Result, 0) +
+       ", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, " +
+       getSpellingArg(Result, 1) + ")")
+          .str();
+  replaceFunc(Result,
+              "prefer open() to creat() because open() allows O_CLOEXEC",
+              ReplacementText);
+}
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/android/CloexecCreatCheck.h b/clang-tidy/android/CloexecCreatCheck.h
new file mode 100644
index 0000000..335990c
--- /dev/null
+++ b/clang-tidy/android/CloexecCreatCheck.h
@@ -0,0 +1,35 @@
+//===--- CloexecCreatCheck.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_ANDROID_CLOEXEC_CREAT_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_CREAT_H
+
+#include "CloexecCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+/// creat() is better to be replaced by open().
+/// Find the usage of creat() and redirect user to use open().
+
+/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-creat.html
+class CloexecCreatCheck : public CloexecCheck {
+public:
+  CloexecCreatCheck(StringRef Name, ClangTidyContext *Context)
+      : CloexecCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_CREAT_H
diff --git a/clang-tidy/android/CloexecDupCheck.cpp b/clang-tidy/android/CloexecDupCheck.cpp
new file mode 100644
index 0000000..ec4ff0a
--- /dev/null
+++ b/clang-tidy/android/CloexecDupCheck.cpp
@@ -0,0 +1,38 @@
+//===--- CloexecDupCheck.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 "CloexecDupCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+void CloexecDupCheck::registerMatchers(MatchFinder *Finder) {
+  registerMatchersImpl(Finder,
+                       functionDecl(returns(isInteger()), hasName("dup"),
+                                    hasParameter(0, hasType(isInteger()))));
+}
+
+void CloexecDupCheck::check(const MatchFinder::MatchResult &Result) {
+  const std::string &ReplacementText =
+      (Twine("fcntl(") + getSpellingArg(Result, 0) + ", F_DUPFD_CLOEXEC)")
+          .str();
+
+  replaceFunc(Result,
+              "prefer fcntl() to dup() because fcntl() allows F_DUPFD_CLOEXEC",
+              ReplacementText);
+}
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/android/CloexecDupCheck.h b/clang-tidy/android/CloexecDupCheck.h
new file mode 100644
index 0000000..c040b38
--- /dev/null
+++ b/clang-tidy/android/CloexecDupCheck.h
@@ -0,0 +1,36 @@
+//===--- CloexecDupCheck.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_ANDROID_CLOEXEC_DUP_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_DUP_H
+
+#include "CloexecCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+/// dup() is better to be replaced by fcntl(), which has close-on-exec flag.
+/// Find the usage of dup() and redirect user to use fcntl().
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-dup.html
+class CloexecDupCheck : public CloexecCheck {
+public:
+  CloexecDupCheck(StringRef Name, ClangTidyContext *Context)
+      : CloexecCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_DUP_H
diff --git a/clang-tidy/android/CloexecEpollCreate1Check.cpp b/clang-tidy/android/CloexecEpollCreate1Check.cpp
new file mode 100644
index 0000000..a424762
--- /dev/null
+++ b/clang-tidy/android/CloexecEpollCreate1Check.cpp
@@ -0,0 +1,33 @@
+//===--- CloexecEpollCreate1Check.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 "CloexecEpollCreate1Check.h"
+#include "../utils/ASTUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+void CloexecEpollCreate1Check::registerMatchers(MatchFinder *Finder) {
+  registerMatchersImpl(
+      Finder, functionDecl(returns(isInteger()), hasName("epoll_create1"),
+                           hasParameter(0, hasType(isInteger()))));
+}
+
+void CloexecEpollCreate1Check::check(const MatchFinder::MatchResult &Result) {
+  insertMacroFlag(Result, /*MarcoFlag=*/"EPOLL_CLOEXEC", /*ArgPos=*/0);
+}
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/android/CloexecEpollCreate1Check.h b/clang-tidy/android/CloexecEpollCreate1Check.h
new file mode 100644
index 0000000..9890d5f
--- /dev/null
+++ b/clang-tidy/android/CloexecEpollCreate1Check.h
@@ -0,0 +1,35 @@
+//===--- CloexecEpollCreate1Check.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_ANDROID_CLOEXEC_EPOLL_CREATE1_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_EPOLL_CREATE1_H
+
+#include "CloexecCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+/// Finds code that uses epoll_create1() without using the EPOLL_CLOEXEC flag.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-epoll-create1.html
+class CloexecEpollCreate1Check : public CloexecCheck {
+public:
+  CloexecEpollCreate1Check(StringRef Name, ClangTidyContext *Context)
+      : CloexecCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_EPOLL_CREATE1_H
diff --git a/clang-tidy/android/CloexecEpollCreateCheck.cpp b/clang-tidy/android/CloexecEpollCreateCheck.cpp
new file mode 100644
index 0000000..7165d24
--- /dev/null
+++ b/clang-tidy/android/CloexecEpollCreateCheck.cpp
@@ -0,0 +1,36 @@
+//===--- CloexecEpollCreateCheck.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 "CloexecEpollCreateCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+void CloexecEpollCreateCheck::registerMatchers(MatchFinder *Finder) {
+  registerMatchersImpl(
+      Finder, functionDecl(returns(isInteger()), hasName("epoll_create"),
+                           hasParameter(0, hasType(isInteger()))));
+}
+
+void CloexecEpollCreateCheck::check(const MatchFinder::MatchResult &Result) {
+  replaceFunc(Result,
+              "prefer epoll_create() to epoll_create1() "
+              "because epoll_create1() allows "
+              "EPOLL_CLOEXEC",
+              "epoll_create1(EPOLL_CLOEXEC)");
+}
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/android/CloexecEpollCreateCheck.h b/clang-tidy/android/CloexecEpollCreateCheck.h
new file mode 100644
index 0000000..21d2b2a
--- /dev/null
+++ b/clang-tidy/android/CloexecEpollCreateCheck.h
@@ -0,0 +1,35 @@
+//===--- CloexecEpollCreateCheck.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_ANDROID_CLOEXEC_EPOLL_CREATE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_EPOLL_CREATE_H
+
+#include "CloexecCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+/// epoll_create() is better to be replaced by epoll_create1().
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-epoll-create.html
+class CloexecEpollCreateCheck : public CloexecCheck {
+public:
+  CloexecEpollCreateCheck(StringRef Name, ClangTidyContext *Context)
+      : CloexecCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_EPOLL_CREATE_H
diff --git a/clang-tidy/android/CloexecFopenCheck.cpp b/clang-tidy/android/CloexecFopenCheck.cpp
new file mode 100644
index 0000000..33058d6
--- /dev/null
+++ b/clang-tidy/android/CloexecFopenCheck.cpp
@@ -0,0 +1,36 @@
+//===--- CloexecFopenCheck.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 "CloexecFopenCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Type.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+void CloexecFopenCheck::registerMatchers(MatchFinder *Finder) {
+  auto CharPointerType = hasType(pointerType(pointee(isAnyCharacter())));
+  registerMatchersImpl(Finder,
+                       functionDecl(isExternC(), returns(asString("FILE *")),
+                                    hasName("fopen"),
+                                    hasParameter(0, CharPointerType),
+                                    hasParameter(1, CharPointerType)));
+}
+
+void CloexecFopenCheck::check(const MatchFinder::MatchResult &Result) {
+  insertStringFlag(Result, /*Mode=*/'e', /*ArgPos=*/1);
+}
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/android/CloexecFopenCheck.h b/clang-tidy/android/CloexecFopenCheck.h
new file mode 100644
index 0000000..1c82b8b
--- /dev/null
+++ b/clang-tidy/android/CloexecFopenCheck.h
@@ -0,0 +1,38 @@
+//===--- CloexecFopenCheck.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_ANDROID_CLOEXEC_FOPEN_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_FOPEN_H
+
+#include "CloexecCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+/// fopen() is suggested to include "e" in their mode string; like "re" would be
+/// better than "r".
+///
+/// This check only works when corresponding argument is StringLiteral. No
+/// constant propagation.
+///
+/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-fopen.html
+class CloexecFopenCheck : public CloexecCheck {
+public:
+  CloexecFopenCheck(StringRef Name, ClangTidyContext *Context)
+      : CloexecCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_FOPEN_H
diff --git a/clang-tidy/android/CloexecInotifyInit1Check.cpp b/clang-tidy/android/CloexecInotifyInit1Check.cpp
new file mode 100644
index 0000000..788de19
--- /dev/null
+++ b/clang-tidy/android/CloexecInotifyInit1Check.cpp
@@ -0,0 +1,33 @@
+//===--- CloexecInotifyInit1Check.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 "CloexecInotifyInit1Check.h"
+#include "../utils/ASTUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+void CloexecInotifyInit1Check::registerMatchers(MatchFinder *Finder) {
+  registerMatchersImpl(
+      Finder, functionDecl(returns(isInteger()), hasName("inotify_init1"),
+                           hasParameter(0, hasType(isInteger()))));
+}
+
+void CloexecInotifyInit1Check::check(const MatchFinder::MatchResult &Result) {
+  insertMacroFlag(Result, /*MarcoFlag=*/"IN_CLOEXEC", /*ArgPos=*/0);
+}
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/android/CloexecInotifyInit1Check.h b/clang-tidy/android/CloexecInotifyInit1Check.h
new file mode 100644
index 0000000..deb04f2
--- /dev/null
+++ b/clang-tidy/android/CloexecInotifyInit1Check.h
@@ -0,0 +1,35 @@
+//===--- CloexecInotifyInit1Check.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_ANDROID_CLOEXEC_INOTIFY_INIT1_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_INOTIFY_INIT1_H
+
+#include "CloexecCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+/// Finds code that uses inotify_init1() without using the IN_CLOEXEC flag.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-inotify-init1.html
+class CloexecInotifyInit1Check : public CloexecCheck {
+public:
+  CloexecInotifyInit1Check(StringRef Name, ClangTidyContext *Context)
+      : CloexecCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_INOTIFY_INIT1_H
diff --git a/clang-tidy/android/CloexecInotifyInitCheck.cpp b/clang-tidy/android/CloexecInotifyInitCheck.cpp
new file mode 100644
index 0000000..0d5a56d
--- /dev/null
+++ b/clang-tidy/android/CloexecInotifyInitCheck.cpp
@@ -0,0 +1,34 @@
+//===--- CloexecInotifyInitCheck.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 "CloexecInotifyInitCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+void CloexecInotifyInitCheck::registerMatchers(MatchFinder *Finder) {
+  registerMatchersImpl(
+      Finder, functionDecl(returns(isInteger()), hasName("inotify_init")));
+}
+
+void CloexecInotifyInitCheck::check(const MatchFinder::MatchResult &Result) {
+  replaceFunc(Result, /*WarningMsg=*/
+              "prefer inotify_init() to inotify_init1() "
+              "because inotify_init1() allows IN_CLOEXEC",
+              /*FixMsg=*/"inotify_init1(IN_CLOEXEC)");
+}
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/android/CloexecInotifyInitCheck.h b/clang-tidy/android/CloexecInotifyInitCheck.h
new file mode 100644
index 0000000..ceeecbe
--- /dev/null
+++ b/clang-tidy/android/CloexecInotifyInitCheck.h
@@ -0,0 +1,35 @@
+//===--- CloexecInotifyInitCheck.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_ANDROID_CLOEXEC_INOTIFY_INIT_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_INOTIFY_INIT_H
+
+#include "CloexecCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+/// inotify_init() is better to be replaced by inotify_init1().
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-inotify-init.html
+class CloexecInotifyInitCheck : public CloexecCheck {
+public:
+  CloexecInotifyInitCheck(StringRef Name, ClangTidyContext *Context)
+      : CloexecCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_INOTIFY_INIT_H
diff --git a/clang-tidy/android/CloexecMemfdCreateCheck.cpp b/clang-tidy/android/CloexecMemfdCreateCheck.cpp
new file mode 100644
index 0000000..4820e2b
--- /dev/null
+++ b/clang-tidy/android/CloexecMemfdCreateCheck.cpp
@@ -0,0 +1,32 @@
+//===--- CloexecMemfdCreateCheck.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 "CloexecMemfdCreateCheck.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+void CloexecMemfdCreateCheck::registerMatchers(MatchFinder *Finder) {
+  auto CharPointerType = hasType(pointerType(pointee(isAnyCharacter())));
+  registerMatchersImpl(
+      Finder, functionDecl(returns(isInteger()), hasName("memfd_create"),
+                           hasParameter(0, CharPointerType),
+                           hasParameter(1, hasType(isInteger()))));
+}
+
+void CloexecMemfdCreateCheck::check(const MatchFinder::MatchResult &Result) {
+  insertMacroFlag(Result, "MFD_CLOEXEC", /*ArgPos=*/1);
+}
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/android/CloexecMemfdCreateCheck.h b/clang-tidy/android/CloexecMemfdCreateCheck.h
new file mode 100644
index 0000000..0fe96f4
--- /dev/null
+++ b/clang-tidy/android/CloexecMemfdCreateCheck.h
@@ -0,0 +1,35 @@
+//===--- CloexecMemfdCreateCheck.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_ANDROID_CLOEXEC_MEMFD_CREATE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_MEMFD_CREATE_H
+
+#include "CloexecCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+/// Finds code that uses memfd_create() without using the MFD_CLOEXEC flag.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-memfd-create.html
+class CloexecMemfdCreateCheck : public CloexecCheck {
+public:
+  CloexecMemfdCreateCheck(StringRef Name, ClangTidyContext *Context)
+      : CloexecCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_MEMFD_CREATE_H
diff --git a/clang-tidy/android/CloexecOpenCheck.cpp b/clang-tidy/android/CloexecOpenCheck.cpp
new file mode 100644
index 0000000..0979280
--- /dev/null
+++ b/clang-tidy/android/CloexecOpenCheck.cpp
@@ -0,0 +1,44 @@
+//===--- CloexecOpenCheck.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 "CloexecOpenCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+void CloexecOpenCheck::registerMatchers(MatchFinder *Finder) {
+  auto CharPointerType = hasType(pointerType(pointee(isAnyCharacter())));
+  registerMatchersImpl(Finder,
+                       functionDecl(isExternC(), returns(isInteger()),
+                                    hasAnyName("open", "open64"),
+                                    hasParameter(0, CharPointerType),
+                                    hasParameter(1, hasType(isInteger()))));
+  registerMatchersImpl(Finder,
+                       functionDecl(isExternC(), returns(isInteger()),
+                                    hasName("openat"),
+                                    hasParameter(0, hasType(isInteger())),
+                                    hasParameter(1, CharPointerType),
+                                    hasParameter(2, hasType(isInteger()))));
+}
+
+void CloexecOpenCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>(FuncDeclBindingStr);
+  assert(FD->param_size() > 1);
+  int ArgPos = (FD->param_size() > 2) ? 2 : 1;
+  insertMacroFlag(Result, /*MarcoFlag=*/"O_CLOEXEC", ArgPos);
+}
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/android/CloexecOpenCheck.h b/clang-tidy/android/CloexecOpenCheck.h
new file mode 100644
index 0000000..c221087
--- /dev/null
+++ b/clang-tidy/android/CloexecOpenCheck.h
@@ -0,0 +1,40 @@
+//===--- CloexecOpenCheck.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_ANDROID_CLOEXEC_OPEN_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_OPEN_H
+
+#include "CloexecCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+/// Finds code that opens file without using the O_CLOEXEC flag.
+///
+/// open(), openat(), and open64() had better to include O_CLOEXEC in their
+/// flags argument. Only consider simple cases that the corresponding argument
+/// is constant or binary operation OR among constants like 'O_CLOEXEC' or
+/// 'O_CLOEXEC | O_RDONLY'. No constant propagation is performed.
+///
+/// Only the symbolic 'O_CLOEXEC' macro definition is checked, not the concrete
+/// value.
+class CloexecOpenCheck : public CloexecCheck {
+public:
+  CloexecOpenCheck(StringRef Name, ClangTidyContext *Context)
+      : CloexecCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_OPEN_H
diff --git a/clang-tidy/android/CloexecSocketCheck.cpp b/clang-tidy/android/CloexecSocketCheck.cpp
new file mode 100644
index 0000000..5bcfbcb
--- /dev/null
+++ b/clang-tidy/android/CloexecSocketCheck.cpp
@@ -0,0 +1,35 @@
+//===--- CloexecSocketCheck.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 "CloexecSocketCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+void CloexecSocketCheck::registerMatchers(MatchFinder *Finder) {
+  registerMatchersImpl(Finder,
+                       functionDecl(isExternC(), returns(isInteger()),
+                                    hasName("socket"),
+                                    hasParameter(0, hasType(isInteger())),
+                                    hasParameter(1, hasType(isInteger())),
+                                    hasParameter(2, hasType(isInteger()))));
+}
+
+void CloexecSocketCheck::check(const MatchFinder::MatchResult &Result) {
+  insertMacroFlag(Result, /*MarcoFlag=*/"SOCK_CLOEXEC", /*ArgPos=*/1);
+}
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/android/CloexecSocketCheck.h b/clang-tidy/android/CloexecSocketCheck.h
new file mode 100644
index 0000000..c1fd01f
--- /dev/null
+++ b/clang-tidy/android/CloexecSocketCheck.h
@@ -0,0 +1,35 @@
+//===--- CloexecSocketCheck.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_ANDROID_CLOEXEC_SOCKET_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_SOCKET_H
+
+#include "CloexecCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace android {
+
+/// Finds code that uses socket() without using the SOCK_CLOEXEC flag.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-socket.html
+class CloexecSocketCheck : public CloexecCheck {
+public:
+  CloexecSocketCheck(StringRef Name, ClangTidyContext *Context)
+      : CloexecCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace android
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_SOCKET_H
diff --git a/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tidy/bugprone/BugproneTidyModule.cpp
new file mode 100644
index 0000000..c350c96
--- /dev/null
+++ b/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -0,0 +1,44 @@
+//===--- BugproneTidyModule.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 "../ClangTidy.h"
+#include "../ClangTidyModule.h"
+#include "../ClangTidyModuleRegistry.h"
+#include "IntegerDivisionCheck.h"
+#include "SuspiciousMemsetUsageCheck.h"
+#include "UndefinedMemoryManipulationCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+class BugproneModule : public ClangTidyModule {
+public:
+  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<IntegerDivisionCheck>(
+        "bugprone-integer-division");
+    CheckFactories.registerCheck<SuspiciousMemsetUsageCheck>(
+        "bugprone-suspicious-memset-usage");
+    CheckFactories.registerCheck<UndefinedMemoryManipulationCheck>(
+        "bugprone-undefined-memory-manipulation");
+  }
+};
+
+} // namespace bugprone
+
+// Register the BugproneTidyModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add<bugprone::BugproneModule>
+    X("bugprone-module", "Adds checks for bugprone code constructs.");
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the BugproneModule.
+volatile int BugproneModuleAnchorSource = 0;
+
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/bugprone/CMakeLists.txt b/clang-tidy/bugprone/CMakeLists.txt
new file mode 100644
index 0000000..0b83c96
--- /dev/null
+++ b/clang-tidy/bugprone/CMakeLists.txt
@@ -0,0 +1,18 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangTidyBugproneModule
+  BugproneTidyModule.cpp
+  IntegerDivisionCheck.cpp
+  SuspiciousMemsetUsageCheck.cpp
+  UndefinedMemoryManipulationCheck.cpp
+
+  LINK_LIBS
+  clangAnalysis
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangLex
+  clangTidy
+  clangTidyUtils
+  clangTooling
+  )
diff --git a/clang-tidy/bugprone/IntegerDivisionCheck.cpp b/clang-tidy/bugprone/IntegerDivisionCheck.cpp
new file mode 100644
index 0000000..1b4eaea
--- /dev/null
+++ b/clang-tidy/bugprone/IntegerDivisionCheck.cpp
@@ -0,0 +1,57 @@
+//===--- IntegerDivisionCheck.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 "IntegerDivisionCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+void IntegerDivisionCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IntType = hasType(isInteger());
+
+  const auto BinaryOperators = binaryOperator(anyOf(
+      hasOperatorName("%"), hasOperatorName("<<"), hasOperatorName(">>"),
+      hasOperatorName("<<"), hasOperatorName("^"), hasOperatorName("|"),
+      hasOperatorName("&"), hasOperatorName("||"), hasOperatorName("&&"),
+      hasOperatorName("<"), hasOperatorName(">"), hasOperatorName("<="),
+      hasOperatorName(">="), hasOperatorName("=="), hasOperatorName("!=")));
+
+  const auto UnaryOperators =
+      unaryOperator(anyOf(hasOperatorName("~"), hasOperatorName("!")));
+
+  const auto Exceptions =
+      anyOf(BinaryOperators, conditionalOperator(), binaryConditionalOperator(),
+            callExpr(IntType), explicitCastExpr(IntType), UnaryOperators);
+
+  Finder->addMatcher(
+      binaryOperator(
+          hasOperatorName("/"), hasLHS(expr(IntType)), hasRHS(expr(IntType)),
+          hasAncestor(
+              castExpr(hasCastKind(CK_IntegralToFloating)).bind("FloatCast")),
+          unless(hasAncestor(
+              expr(Exceptions,
+                   hasAncestor(castExpr(equalsBoundNode("FloatCast")))))))
+          .bind("IntDiv"),
+      this);
+}
+
+void IntegerDivisionCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *IntDiv = Result.Nodes.getNodeAs<BinaryOperator>("IntDiv");
+  diag(IntDiv->getLocStart(), "result of integer division used in a floating "
+                              "point context; possible loss of precision");
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/bugprone/IntegerDivisionCheck.h b/clang-tidy/bugprone/IntegerDivisionCheck.h
new file mode 100644
index 0000000..307e493
--- /dev/null
+++ b/clang-tidy/bugprone/IntegerDivisionCheck.h
@@ -0,0 +1,36 @@
+//===--- IntegerDivisionCheck.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_INTEGER_DIVISION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INTEGER_DIVISION_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Finds cases where integer division in a floating point context is likely to
+/// cause unintended loss of precision.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-integer-division.html
+class IntegerDivisionCheck : public ClangTidyCheck {
+public:
+  IntegerDivisionCheck(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_INTEGER_DIVISION_H
diff --git a/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.cpp b/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.cpp
new file mode 100644
index 0000000..8e11a43
--- /dev/null
+++ b/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.cpp
@@ -0,0 +1,127 @@
+//===--- SuspiciousMemsetUsageCheck.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 "SuspiciousMemsetUsageCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+void SuspiciousMemsetUsageCheck::registerMatchers(MatchFinder *Finder) {
+  // Note: void *memset(void *buffer, int fill_char, size_t byte_count);
+  // Look for memset(x, '0', z). Probably memset(x, 0, z) was intended.
+  Finder->addMatcher(
+      callExpr(
+          callee(functionDecl(hasName("::memset"))),
+          hasArgument(1, characterLiteral(equals(static_cast<unsigned>('0')))
+                             .bind("char-zero-fill")),
+          unless(
+              eachOf(hasArgument(0, anyOf(hasType(pointsTo(isAnyCharacter())),
+                                          hasType(arrayType(hasElementType(
+                                              isAnyCharacter()))))),
+                     isInTemplateInstantiation()))),
+      this);
+
+  // Look for memset with an integer literal in its fill_char argument.
+  // Will check if it gets truncated.
+  Finder->addMatcher(callExpr(callee(functionDecl(hasName("::memset"))),
+                              hasArgument(1, integerLiteral().bind("num-fill")),
+                              unless(isInTemplateInstantiation())),
+                     this);
+
+  // Look for memset(x, y, 0) as that is most likely an argument swap.
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(hasName("::memset"))),
+               unless(hasArgument(1, anyOf(characterLiteral(equals(
+                                               static_cast<unsigned>('0'))),
+                                           integerLiteral()))),
+               unless(isInTemplateInstantiation()))
+          .bind("call"),
+      this);
+}
+
+void SuspiciousMemsetUsageCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *CharZeroFill =
+          Result.Nodes.getNodeAs<CharacterLiteral>("char-zero-fill")) {
+    // Case 1: fill_char of memset() is a character '0'. Probably an
+    // integer zero was intended.
+
+    SourceRange CharRange = CharZeroFill->getSourceRange();
+    auto Diag =
+        diag(CharZeroFill->getLocStart(), "memset fill value is char '0', "
+                                          "potentially mistaken for int 0");
+
+    // Only suggest a fix if no macros are involved.
+    if (CharRange.getBegin().isMacroID())
+      return;
+    Diag << FixItHint::CreateReplacement(
+        CharSourceRange::getTokenRange(CharRange), "0");
+  }
+
+  else if (const auto *NumFill =
+               Result.Nodes.getNodeAs<IntegerLiteral>("num-fill")) {
+    // Case 2: fill_char of memset() is larger in size than an unsigned char
+    // so it gets truncated during conversion.
+
+    llvm::APSInt NumValue;
+    const auto UCharMax = (1 << Result.Context->getCharWidth()) - 1;
+    if (!NumFill->EvaluateAsInt(NumValue, *Result.Context) ||
+        (NumValue >= 0 && NumValue <= UCharMax))
+      return;
+
+    diag(NumFill->getLocStart(), "memset fill value is out of unsigned "
+                                 "character range, gets truncated");
+  }
+
+  else if (const auto *Call = Result.Nodes.getNodeAs<CallExpr>("call")) {
+    // Case 3: byte_count of memset() is zero. This is most likely an
+    // argument swap.
+
+    const Expr *FillChar = Call->getArg(1);
+    const Expr *ByteCount = Call->getArg(2);
+
+    // Return if `byte_count` is not zero at compile time.
+    llvm::APSInt Value1, Value2;
+    if (ByteCount->isValueDependent() ||
+        !ByteCount->EvaluateAsInt(Value2, *Result.Context) || Value2 != 0)
+      return;
+
+    // Return if `fill_char` is known to be zero or negative at compile
+    // time. In these cases, swapping the args would be a nop, or
+    // introduce a definite bug. The code is likely correct.
+    if (!FillChar->isValueDependent() &&
+        FillChar->EvaluateAsInt(Value1, *Result.Context) &&
+        (Value1 == 0 || Value1.isNegative()))
+      return;
+
+    // `byte_count` is known to be zero at compile time, and `fill_char` is
+    // either not known or known to be a positive integer. Emit a warning
+    // and fix-its to swap the arguments.
+    auto D = diag(Call->getLocStart(),
+                  "memset of size zero, potentially swapped arguments");
+    StringRef RHSString = tooling::fixit::getText(*ByteCount, *Result.Context);
+    StringRef LHSString = tooling::fixit::getText(*FillChar, *Result.Context);
+    if (LHSString.empty() || RHSString.empty())
+      return;
+
+    D << tooling::fixit::createReplacement(*FillChar, RHSString)
+      << tooling::fixit::createReplacement(*ByteCount, LHSString);
+  }
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.h b/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.h
new file mode 100644
index 0000000..1c0d1bc
--- /dev/null
+++ b/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.h
@@ -0,0 +1,35 @@
+//===--- SuspiciousMemsetUsageCheck.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_SUSPICIOUS_MEMSET_USAGE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUS_MEMSET_USAGE_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Finds memset calls with potential mistakes in their arguments.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-suspicious-memset-usage.html
+class SuspiciousMemsetUsageCheck : public ClangTidyCheck {
+public:
+  SuspiciousMemsetUsageCheck(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_SUSPICIOUS_MEMSET_USAGE_H
diff --git a/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.cpp b/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.cpp
new file mode 100644
index 0000000..ebfe517
--- /dev/null
+++ b/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.cpp
@@ -0,0 +1,71 @@
+//===--- UndefinedMemoryManipulationCheck.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 "UndefinedMemoryManipulationCheck.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(CXXRecordDecl, isNotTriviallyCopyable) {
+  // For incomplete types, assume they are TriviallyCopyable.
+  return Node.hasDefinition() ? !Node.isTriviallyCopyable() : false;
+}
+} // namespace
+
+void UndefinedMemoryManipulationCheck::registerMatchers(MatchFinder *Finder) {
+  const auto NotTriviallyCopyableObject =
+      hasType(ast_matchers::hasCanonicalType(
+          pointsTo(cxxRecordDecl(isNotTriviallyCopyable()))));
+
+  // Check whether destination object is not TriviallyCopyable.
+  // Applicable to all three memory manipulation functions.
+  Finder->addMatcher(callExpr(callee(functionDecl(hasAnyName(
+                                  "::memset", "::memcpy", "::memmove"))),
+                              hasArgument(0, NotTriviallyCopyableObject))
+                         .bind("dest"),
+                     this);
+
+  // Check whether source object is not TriviallyCopyable.
+  // Only applicable to memcpy() and memmove().
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(hasAnyName("::memcpy", "::memmove"))),
+               hasArgument(1, NotTriviallyCopyableObject))
+          .bind("src"),
+      this);
+}
+
+void UndefinedMemoryManipulationCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  if (const auto *Call = Result.Nodes.getNodeAs<CallExpr>("dest")) {
+    QualType DestType = Call->getArg(0)->IgnoreImplicit()->getType();
+    if (!DestType->getPointeeType().isNull())
+      DestType = DestType->getPointeeType();
+    diag(Call->getLocStart(), "undefined behavior, destination object type %0 "
+                              "is not TriviallyCopyable")
+        << DestType;
+  }
+  if (const auto *Call = Result.Nodes.getNodeAs<CallExpr>("src")) {
+    QualType SourceType = Call->getArg(1)->IgnoreImplicit()->getType();
+    if (!SourceType->getPointeeType().isNull())
+      SourceType = SourceType->getPointeeType();
+    diag(Call->getLocStart(),
+         "undefined behavior, source object type %0 is not TriviallyCopyable")
+        << SourceType;
+  }
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.h b/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.h
new file mode 100644
index 0000000..64d6c56
--- /dev/null
+++ b/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.h
@@ -0,0 +1,37 @@
+//===--- UndefinedMemoryManipulationCheck.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_UNDEFINED_MEMORY_MANIPULATION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNDEFINED_MEMORY_MANIPULATION_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Finds calls of memory manipulation functions ``memset()``, ``memcpy()`` and
+/// ``memmove()`` on not TriviallyCopyable objects resulting in undefined
+/// behavior.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-undefined-memory-manipulation.html
+class UndefinedMemoryManipulationCheck : public ClangTidyCheck {
+public:
+  UndefinedMemoryManipulationCheck(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_UNDEFINED_MEMORY_MANIPULATION_H
diff --git a/clang-tidy/cppcoreguidelines/CMakeLists.txt b/clang-tidy/cppcoreguidelines/CMakeLists.txt
index 43ac55d..70ee599 100644
--- a/clang-tidy/cppcoreguidelines/CMakeLists.txt
+++ b/clang-tidy/cppcoreguidelines/CMakeLists.txt
@@ -4,6 +4,7 @@
   CppCoreGuidelinesTidyModule.cpp
   InterfacesGlobalInitCheck.cpp
   NoMallocCheck.cpp
+  OwningMemoryCheck.cpp
   ProBoundsArrayToPointerDecayCheck.cpp
   ProBoundsConstantArrayIndexCheck.cpp
   ProBoundsPointerArithmeticCheck.cpp
diff --git a/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp b/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
index 6b9de8d..454adc9 100644
--- a/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
+++ b/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
@@ -13,6 +13,7 @@
 #include "../misc/UnconventionalAssignOperatorCheck.h"
 #include "InterfacesGlobalInitCheck.h"
 #include "NoMallocCheck.h"
+#include "OwningMemoryCheck.h"
 #include "ProBoundsArrayToPointerDecayCheck.h"
 #include "ProBoundsConstantArrayIndexCheck.h"
 #include "ProBoundsPointerArithmeticCheck.h"
@@ -37,6 +38,8 @@
     CheckFactories.registerCheck<InterfacesGlobalInitCheck>(
         "cppcoreguidelines-interfaces-global-init");
     CheckFactories.registerCheck<NoMallocCheck>("cppcoreguidelines-no-malloc");
+    CheckFactories.registerCheck<OwningMemoryCheck>(
+        "cppcoreguidelines-owning-memory");
     CheckFactories.registerCheck<ProBoundsArrayToPointerDecayCheck>(
         "cppcoreguidelines-pro-bounds-array-to-pointer-decay");
     CheckFactories.registerCheck<ProBoundsConstantArrayIndexCheck>(
diff --git a/clang-tidy/cppcoreguidelines/NoMallocCheck.cpp b/clang-tidy/cppcoreguidelines/NoMallocCheck.cpp
index eda8907..8b9b760 100644
--- a/clang-tidy/cppcoreguidelines/NoMallocCheck.cpp
+++ b/clang-tidy/cppcoreguidelines/NoMallocCheck.cpp
@@ -29,7 +29,7 @@
       utils::options::parseStringList(FunctionNames);
   return hasAnyName(std::vector<StringRef>(NameList.begin(), NameList.end()));
 }
-}
+} // namespace
 
 void NoMallocCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
   Options.store(Opts, "Allocations", AllocList);
diff --git a/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp b/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp
new file mode 100644
index 0000000..6c86e05
--- /dev/null
+++ b/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp
@@ -0,0 +1,394 @@
+//===--- OwningMemoryCheck.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 "OwningMemoryCheck.h"
+#include "../utils/Matchers.h"
+#include "../utils/OptionsUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include <string>
+#include <vector>
+
+using namespace clang::ast_matchers;
+using namespace clang::ast_matchers::internal;
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+// FIXME: Copied from 'NoMallocCheck.cpp'. Has to be refactored into 'util' or
+// something like that.
+namespace {
+Matcher<FunctionDecl> hasAnyListedName(const std::string &FunctionNames) {
+  const std::vector<std::string> NameList =
+      utils::options::parseStringList(FunctionNames);
+  return hasAnyName(std::vector<StringRef>(NameList.begin(), NameList.end()));
+}
+} // namespace
+
+void OwningMemoryCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "LegacyResourceProducers", LegacyResourceProducers);
+  Options.store(Opts, "LegacyResourceConsumers", LegacyResourceConsumers);
+}
+
+/// Match common cases, where the owner semantic is relevant, like function
+/// calls, delete expressions and others.
+void OwningMemoryCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus11)
+    return;
+
+  const auto OwnerDecl = typeAliasTemplateDecl(hasName("::gsl::owner"));
+  const auto IsOwnerType = hasType(OwnerDecl);
+
+  const auto LegacyCreatorFunctions = hasAnyListedName(LegacyResourceProducers);
+  const auto LegacyConsumerFunctions =
+      hasAnyListedName(LegacyResourceConsumers);
+
+  // Legacy functions that are use for resource management but cannot be
+  // updated to use `gsl::owner<>`, like standard C memory management.
+  const auto CreatesLegacyOwner =
+      callExpr(callee(functionDecl(LegacyCreatorFunctions)));
+  // C-style functions like `::malloc()` sometimes create owners as void*
+  // which is expected to be cast to the correct type in C++. This case
+  // must be catched explicitly.
+  const auto LegacyOwnerCast =
+      castExpr(hasSourceExpression(CreatesLegacyOwner));
+  // Functions that do manual resource management but cannot be updated to use
+  // owner. Best example is `::free()`.
+  const auto LegacyOwnerConsumers = functionDecl(LegacyConsumerFunctions);
+
+  const auto CreatesOwner =
+      anyOf(cxxNewExpr(),
+            callExpr(callee(
+                functionDecl(returns(qualType(hasDeclaration(OwnerDecl)))))),
+            CreatesLegacyOwner, LegacyOwnerCast);
+
+  const auto ConsideredOwner = eachOf(IsOwnerType, CreatesOwner);
+
+  // Find delete expressions that delete non-owners.
+  Finder->addMatcher(
+      cxxDeleteExpr(
+          hasDescendant(
+              declRefExpr(unless(ConsideredOwner)).bind("deleted_variable")))
+          .bind("delete_expr"),
+      this);
+
+  // Ignoring the implicit casts is vital because the legacy owners do not work
+  // with the 'owner<>' annotation and therefore always implicitly cast to the
+  // legacy type (even 'void *').
+  //
+  // Furthermore, legacy owner functions are assumed to use raw pointers for
+  // resources. This check assumes that all pointer arguments of a legacy
+  // functions shall be 'gsl::owner<>'.
+  Finder->addMatcher(
+      callExpr(
+          allOf(callee(LegacyOwnerConsumers),
+                hasAnyArgument(allOf(unless(ignoringImpCasts(ConsideredOwner)),
+                                     hasType(pointerType())))))
+          .bind("legacy_consumer"),
+      this);
+
+  // Matching assignment to owners, with the rhs not being an owner nor creating
+  // one.
+  Finder->addMatcher(binaryOperator(allOf(matchers::isAssignmentOperator(),
+                                          hasLHS(IsOwnerType),
+                                          hasRHS(unless(ConsideredOwner))))
+                         .bind("owner_assignment"),
+                     this);
+
+  // Matching initialization of owners with non-owners, nor creating owners.
+  Finder->addMatcher(
+      namedDecl(
+          varDecl(allOf(hasInitializer(unless(ConsideredOwner)), IsOwnerType))
+              .bind("owner_initialization")),
+      this);
+
+  const auto HasConstructorInitializerForOwner =
+      has(cxxConstructorDecl(forEachConstructorInitializer(
+          cxxCtorInitializer(allOf(isMemberInitializer(), forField(IsOwnerType),
+                                   withInitializer(
+                                       // Avoid templatesdeclaration with
+                                       // excluding parenListExpr.
+                                       allOf(unless(ConsideredOwner),
+                                             unless(parenListExpr())))))
+              .bind("owner_member_initializer"))));
+
+  // Match class member initialization that expects owners, but does not get
+  // them.
+  Finder->addMatcher(cxxRecordDecl(HasConstructorInitializerForOwner), this);
+
+  // Matching on assignment operations where the RHS is a newly created owner,
+  // but the LHS is not an owner.
+  Finder->addMatcher(
+      binaryOperator(allOf(matchers::isAssignmentOperator(),
+                           hasLHS(unless(IsOwnerType)), hasRHS(CreatesOwner)))
+          .bind("bad_owner_creation_assignment"),
+      this);
+
+  // Matching on initialization operations where the initial value is a newly
+  // created owner, but the LHS is not an owner.
+  Finder->addMatcher(
+      namedDecl(varDecl(eachOf(allOf(hasInitializer(CreatesOwner),
+                                     unless(IsOwnerType)),
+                               allOf(hasInitializer(ConsideredOwner),
+                                     hasType(autoType().bind("deduced_type")))))
+                    .bind("bad_owner_creation_variable")),
+      this);
+
+  // Match on all function calls that expect owners as arguments, but didn't
+  // get them.
+  Finder->addMatcher(
+      callExpr(forEachArgumentWithParam(
+          expr(unless(ConsideredOwner)).bind("expected_owner_argument"),
+          parmVarDecl(IsOwnerType))),
+      this);
+
+  // Matching for function calls where one argument is a created owner, but the
+  // parameter type is not an owner.
+  Finder->addMatcher(callExpr(forEachArgumentWithParam(
+                         expr(CreatesOwner).bind("bad_owner_creation_argument"),
+                         parmVarDecl(unless(IsOwnerType))
+                             .bind("bad_owner_creation_parameter"))),
+                     this);
+
+  // Matching on functions, that return an owner/resource, but don't declare
+  // their return type as owner.
+  Finder->addMatcher(
+      functionDecl(
+          allOf(hasDescendant(returnStmt(hasReturnValue(ConsideredOwner))
+                                  .bind("bad_owner_return")),
+                unless(returns(qualType(hasDeclaration(OwnerDecl))))))
+          .bind("function_decl"),
+      this);
+
+  // Match on classes that have an owner as member, but don't declare a
+  // destructor to properly release the owner.
+  Finder->addMatcher(
+      cxxRecordDecl(
+          allOf(
+              has(fieldDecl(IsOwnerType).bind("undestructed_owner_member")),
+              anyOf(unless(has(cxxDestructorDecl())),
+                    has(cxxDestructorDecl(anyOf(isDefaulted(), isDeleted()))))))
+          .bind("non_destructor_class"),
+      this);
+}
+
+void OwningMemoryCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto &Nodes = Result.Nodes;
+
+  bool CheckExecuted = false;
+  CheckExecuted |= handleDeletion(Nodes);
+  CheckExecuted |= handleLegacyConsumers(Nodes);
+  CheckExecuted |= handleExpectedOwner(Nodes);
+  CheckExecuted |= handleAssignmentAndInit(Nodes);
+  CheckExecuted |= handleAssignmentFromNewOwner(Nodes);
+  CheckExecuted |= handleReturnValues(Nodes);
+  CheckExecuted |= handleOwnerMembers(Nodes);
+
+  assert(CheckExecuted &&
+         "None of the subroutines executed, logic error in matcher!");
+}
+
+bool OwningMemoryCheck::handleDeletion(const BoundNodes &Nodes) {
+  // Result of delete matchers.
+  const auto *DeleteStmt = Nodes.getNodeAs<CXXDeleteExpr>("delete_expr");
+  const auto *DeletedVariable =
+      Nodes.getNodeAs<DeclRefExpr>("deleted_variable");
+
+  // Deletion of non-owners, with `delete variable;`
+  if (DeleteStmt) {
+    diag(DeleteStmt->getLocStart(),
+         "deleting a pointer through a type that is "
+         "not marked 'gsl::owner<>'; consider using a "
+         "smart pointer instead")
+        << DeletedVariable->getSourceRange();
+
+    // FIXME: The declaration of the variable that was deleted can be
+    // rewritten.
+    const ValueDecl *Decl = DeletedVariable->getDecl();
+    diag(Decl->getLocStart(), "variable declared here", DiagnosticIDs::Note)
+        << Decl->getSourceRange();
+
+    return true;
+  }
+  return false;
+}
+
+bool OwningMemoryCheck::handleLegacyConsumers(const BoundNodes &Nodes) {
+  // Result of matching for legacy consumer-functions like `::free()`.
+  const auto *LegacyConsumer = Nodes.getNodeAs<CallExpr>("legacy_consumer");
+
+  // FIXME: `freopen` should be handled seperately because it takes the filename
+  // as a pointer, which should not be an owner. The argument that is an owner
+  // is known and the false positive coming from the filename can be avoided.
+  if (LegacyConsumer) {
+    diag(LegacyConsumer->getLocStart(),
+         "calling legacy resource function without passing a 'gsl::owner<>'")
+        << LegacyConsumer->getSourceRange();
+    return true;
+  }
+  return false;
+}
+
+bool OwningMemoryCheck::handleExpectedOwner(const BoundNodes &Nodes) {
+  // Result of function call matchers.
+  const auto *ExpectedOwner = Nodes.getNodeAs<Expr>("expected_owner_argument");
+
+  // Expected function argument to be owner.
+  if (ExpectedOwner) {
+    diag(ExpectedOwner->getLocStart(),
+         "expected argument of type 'gsl::owner<>'; got %0")
+        << ExpectedOwner->getType() << ExpectedOwner->getSourceRange();
+    return true;
+  }
+  return false;
+}
+
+/// Assignment and initialization of owner variables.
+bool OwningMemoryCheck::handleAssignmentAndInit(const BoundNodes &Nodes) {
+  const auto *OwnerAssignment =
+      Nodes.getNodeAs<BinaryOperator>("owner_assignment");
+  const auto *OwnerInitialization =
+      Nodes.getNodeAs<VarDecl>("owner_initialization");
+  const auto *OwnerInitializer =
+      Nodes.getNodeAs<CXXCtorInitializer>("owner_member_initializer");
+
+  // Assignments to owners.
+  if (OwnerAssignment) {
+    diag(OwnerAssignment->getLocStart(),
+         "expected assignment source to be of type 'gsl::owner<>'; got %0")
+        << OwnerAssignment->getRHS()->getType()
+        << OwnerAssignment->getSourceRange();
+    return true;
+  }
+
+  // Initialization of owners.
+  if (OwnerInitialization) {
+    diag(OwnerInitialization->getLocStart(),
+         "expected initialization with value of type 'gsl::owner<>'; got %0")
+        << OwnerInitialization->getAnyInitializer()->getType()
+        << OwnerInitialization->getSourceRange();
+    return true;
+  }
+
+  // Initializer of class constructors that initialize owners.
+  if (OwnerInitializer) {
+    diag(OwnerInitializer->getSourceLocation(),
+         "expected initialization of owner member variable with value of type "
+         "'gsl::owner<>'; got %0")
+        // FIXME: the expression from getInit has type 'void', but the type
+        // of the supplied argument would be of interest.
+        << OwnerInitializer->getInit()->getType()
+        << OwnerInitializer->getSourceRange();
+    return true;
+  }
+  return false;
+}
+
+/// Problematic assignment and initializations, since the assigned value is a
+/// newly created owner.
+bool OwningMemoryCheck::handleAssignmentFromNewOwner(const BoundNodes &Nodes) {
+  const auto *BadOwnerAssignment =
+      Nodes.getNodeAs<BinaryOperator>("bad_owner_creation_assignment");
+  const auto *BadOwnerInitialization =
+      Nodes.getNodeAs<VarDecl>("bad_owner_creation_variable");
+
+  const auto *BadOwnerArgument =
+      Nodes.getNodeAs<Expr>("bad_owner_creation_argument");
+  const auto *BadOwnerParameter =
+      Nodes.getNodeAs<ParmVarDecl>("bad_owner_creation_parameter");
+
+  // Bad assignments to non-owners, where the RHS is a newly created owner.
+  if (BadOwnerAssignment) {
+    diag(BadOwnerAssignment->getLocStart(),
+         "assigning newly created 'gsl::owner<>' to non-owner %0")
+        << BadOwnerAssignment->getLHS()->getType()
+        << BadOwnerAssignment->getSourceRange();
+    return true;
+  }
+
+  // Bad initialization of non-owners, where the RHS is a newly created owner.
+  if (BadOwnerInitialization) {
+    diag(BadOwnerInitialization->getLocStart(),
+         "initializing non-owner %0 with a newly created 'gsl::owner<>'")
+        << BadOwnerInitialization->getType()
+        << BadOwnerInitialization->getSourceRange();
+
+    // FIXME: FixitHint to rewrite the type of the initialized variable
+    // as 'gsl::owner<OriginalType>'
+
+    // If the type of the variable was deduced, the wrapping owner typedef is
+    // eliminated, therefore the check emits a special note for that case.
+    if (Nodes.getNodeAs<AutoType>("deduced_type")) {
+      diag(BadOwnerInitialization->getLocStart(),
+           "type deduction did not result in an owner", DiagnosticIDs::Note);
+    }
+    return true;
+  }
+
+  // Function call, where one arguments is a newly created owner, but the
+  // parameter type is not.
+  if (BadOwnerArgument) {
+    assert(BadOwnerParameter &&
+           "parameter for the problematic argument not found");
+    diag(BadOwnerArgument->getLocStart(), "initializing non-owner argument of "
+                                          "type %0 with a newly created "
+                                          "'gsl::owner<>'")
+        << BadOwnerParameter->getType() << BadOwnerArgument->getSourceRange();
+    return true;
+  }
+  return false;
+}
+
+bool OwningMemoryCheck::handleReturnValues(const BoundNodes &Nodes) {
+  // Function return statements, that are owners/resources, but the function
+  // declaration does not declare its return value as owner.
+  const auto *BadReturnType = Nodes.getNodeAs<ReturnStmt>("bad_owner_return");
+  const auto *Function = Nodes.getNodeAs<FunctionDecl>("function_decl");
+
+  // Function return values, that should be owners but aren't.
+  if (BadReturnType) {
+    // The returned value is a resource or variable that was not annotated with
+    // owner<> and the function return type is not owner<>.
+    diag(BadReturnType->getLocStart(),
+         "returning a newly created resource of "
+         "type %0 or 'gsl::owner<>' from a "
+         "function whose return type is not 'gsl::owner<>'")
+        << Function->getReturnType() << BadReturnType->getSourceRange();
+
+    // FIXME: Rewrite the return type as 'gsl::owner<OriginalType>'
+    return true;
+  }
+  return false;
+}
+
+bool OwningMemoryCheck::handleOwnerMembers(const BoundNodes &Nodes) {
+  // Classes, that have owners as member, but do not declare destructors
+  // accordingly.
+  const auto *BadClass = Nodes.getNodeAs<CXXRecordDecl>("non_destructor_class");
+
+  // Classes, that contains owners, but do not declare destructors.
+  if (BadClass) {
+    const auto *DeclaredOwnerMember =
+        Nodes.getNodeAs<FieldDecl>("undestructed_owner_member");
+    assert(DeclaredOwnerMember &&
+           "match on class with bad destructor but without a declared owner");
+
+    diag(DeclaredOwnerMember->getLocStart(),
+         "member variable of type 'gsl::owner<>' requires the class %0 to "
+         "implement a destructor to release the owned resource")
+        << BadClass;
+    return true;
+  }
+  return false;
+}
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/cppcoreguidelines/OwningMemoryCheck.h b/clang-tidy/cppcoreguidelines/OwningMemoryCheck.h
new file mode 100644
index 0000000..e68e4c0
--- /dev/null
+++ b/clang-tidy/cppcoreguidelines/OwningMemoryCheck.h
@@ -0,0 +1,63 @@
+//===--- OwningMemoryCheck.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_CPPCOREGUIDELINES_OWNING_MEMORY_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_OWNING_MEMORY_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+/// Checks for common use cases for gsl::owner and enforces the unique owner
+/// nature of it whenever possible.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-owning-memory.html
+class OwningMemoryCheck : public ClangTidyCheck {
+public:
+  OwningMemoryCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context),
+        LegacyResourceProducers(Options.get(
+            "LegacyResourceProducers", "::malloc;::aligned_alloc;::realloc;"
+                                       "::calloc;::fopen;::freopen;::tmpfile")),
+        LegacyResourceConsumers(Options.get(
+            "LegacyResourceConsumers", "::free;::realloc;::freopen;::fclose")) {
+  }
+
+  /// Make configuration of checker discoverable.
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  bool handleDeletion(const ast_matchers::BoundNodes &Nodes);
+  bool handleLegacyConsumers(const ast_matchers::BoundNodes &Nodes);
+  bool handleExpectedOwner(const ast_matchers::BoundNodes &Nodes);
+  bool handleAssignmentAndInit(const ast_matchers::BoundNodes &Nodes);
+  bool handleAssignmentFromNewOwner(const ast_matchers::BoundNodes &Nodes);
+  bool handleReturnValues(const ast_matchers::BoundNodes &Nodes);
+  bool handleOwnerMembers(const ast_matchers::BoundNodes &Nodes);
+
+  /// List of old C-style functions that create resources.
+  /// Defaults to
+  /// `::malloc;::aligned_alloc;::realloc;::calloc;::fopen;::freopen;::tmpfile`.
+  const std::string LegacyResourceProducers;
+  /// List of old C-style functions that consume or release resources.
+  /// Defaults to `::free;::realloc;::freopen;::fclose`.
+  const std::string LegacyResourceConsumers;
+};
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_OWNING_MEMORY_H
diff --git a/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp b/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp
index 3844f68..a81496e 100644
--- a/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp
+++ b/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp
@@ -23,7 +23,7 @@
     StringRef Name, ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context), GslHeader(Options.get("GslHeader", "")),
       IncludeStyle(utils::IncludeSorter::parseIncludeStyle(
-          Options.get("IncludeStyle", "llvm"))) {}
+          Options.getLocalOrGlobal("IncludeStyle", "llvm"))) {}
 
 void ProBoundsConstantArrayIndexCheck::storeOptions(
     ClangTidyOptions::OptionMap &Opts) {
diff --git a/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp b/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
index 16955f8..4a7aa50 100644
--- a/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
+++ b/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
@@ -32,22 +32,16 @@
 }
 
 // Iterate over all the fields in a record type, both direct and indirect (e.g.
-// if the record contains an anonmyous struct). If OneFieldPerUnion is true and
-// the record type (or indirect field) is a union, forEachField will stop after
-// the first field.
+// if the record contains an anonmyous struct).
 template <typename T, typename Func>
-void forEachField(const RecordDecl &Record, const T &Fields,
-                  bool OneFieldPerUnion, Func &&Fn) {
+void forEachField(const RecordDecl &Record, const T &Fields, Func &&Fn) {
   for (const FieldDecl *F : Fields) {
     if (F->isAnonymousStructOrUnion()) {
       if (const CXXRecordDecl *R = F->getType()->getAsCXXRecordDecl())
-        forEachField(*R, R->fields(), OneFieldPerUnion, Fn);
+        forEachField(*R, R->fields(), Fn);
     } else {
       Fn(F);
     }
-
-    if (OneFieldPerUnion && Record.isUnion())
-      break;
   }
 }
 
@@ -227,7 +221,7 @@
       Decls.emplace_back(Decl);
     }
   }
-  forEachField(ClassDecl, ClassDecl.fields(), false,
+  forEachField(ClassDecl, ClassDecl.fields(),
                [&](const FieldDecl *F) { Decls.push_back(F); });
 }
 
@@ -353,7 +347,7 @@
 
   // Gather all fields (direct and indirect) that need to be initialized.
   SmallPtrSet<const FieldDecl *, 16> FieldsToInit;
-  forEachField(ClassDecl, ClassDecl.fields(), false, [&](const FieldDecl *F) {
+  forEachField(ClassDecl, ClassDecl.fields(), [&](const FieldDecl *F) {
     if (!F->hasInClassInitializer() &&
         utils::type_traits::isTriviallyDefaultConstructible(F->getType(),
                                                             Context) &&
@@ -379,12 +373,12 @@
   // Collect all fields in order, both direct fields and indirect fields from
   // anonmyous record types.
   SmallVector<const FieldDecl *, 16> OrderedFields;
-  forEachField(ClassDecl, ClassDecl.fields(), false,
+  forEachField(ClassDecl, ClassDecl.fields(),
                [&](const FieldDecl *F) { OrderedFields.push_back(F); });
 
   // Collect all the fields we need to initialize, including indirect fields.
   SmallPtrSet<const FieldDecl *, 16> AllFieldsToInit;
-  forEachField(ClassDecl, FieldsToInit, false,
+  forEachField(ClassDecl, FieldsToInit,
                [&](const FieldDecl *F) { AllFieldsToInit.insert(F); });
   if (AllFieldsToInit.empty())
     return;
@@ -404,11 +398,16 @@
   // Collect all fields but only suggest a fix for the first member of unions,
   // as initializing more than one union member is an error.
   SmallPtrSet<const FieldDecl *, 16> FieldsToFix;
-  forEachField(ClassDecl, FieldsToInit, true, [&](const FieldDecl *F) {
+  SmallPtrSet<const RecordDecl *, 4> UnionsSeen;
+  forEachField(ClassDecl, OrderedFields, [&](const FieldDecl *F) {
+    if (!FieldsToInit.count(F))
+      return;
     // Don't suggest fixes for enums because we don't know a good default.
     // Don't suggest fixes for bitfields because in-class initialization is not
     // possible.
-    if (!F->getType()->isEnumeralType() && !F->isBitField())
+    if (F->getType()->isEnumeralType() || F->isBitField())
+      return;
+    if (!F->getParent()->isUnion() || UnionsSeen.insert(F->getParent()).second)
       FieldsToFix.insert(F);
   });
   if (FieldsToFix.empty())
@@ -449,6 +448,9 @@
 
   // Remove any bases that were explicitly written in the initializer list.
   if (Ctor) {
+    if (Ctor->isImplicit())
+      return;
+
     for (const CXXCtorInitializer *Init : Ctor->inits()) {
       if (Init->isBaseInitializer() && Init->isWritten())
         BasesToInit.erase(Init->getBaseClass()->getAsCXXRecordDecl());
diff --git a/clang-tidy/google/AvoidCStyleCastsCheck.cpp b/clang-tidy/google/AvoidCStyleCastsCheck.cpp
index b3caf91..80cc475 100644
--- a/clang-tidy/google/AvoidCStyleCastsCheck.cpp
+++ b/clang-tidy/google/AvoidCStyleCastsCheck.cpp
@@ -58,10 +58,9 @@
 
 void AvoidCStyleCastsCheck::check(const MatchFinder::MatchResult &Result) {
   const auto *CastExpr = Result.Nodes.getNodeAs<CStyleCastExpr>("cast");
-  auto ParenRange = CharSourceRange::getTokenRange(CastExpr->getLParenLoc(),
-                                                   CastExpr->getRParenLoc());
+
   // Ignore casts in macros.
-  if (ParenRange.getBegin().isMacroID() || ParenRange.getEnd().isMacroID())
+  if (CastExpr->getExprLoc().isMacroID())
     return;
 
   // Casting to void is an idiomatic way to mute "unused variable" and similar
@@ -82,6 +81,9 @@
   const QualType SourceType = SourceTypeAsWritten.getCanonicalType();
   const QualType DestType = DestTypeAsWritten.getCanonicalType();
 
+  auto ReplaceRange = CharSourceRange::getCharRange(
+      CastExpr->getLParenLoc(), CastExpr->getSubExprAsWritten()->getLocStart());
+
   bool FnToFnCast =
       isFunction(SourceTypeAsWritten) && isFunction(DestTypeAsWritten);
 
@@ -92,7 +94,7 @@
     // pointer/reference types.
     if (SourceTypeAsWritten == DestTypeAsWritten) {
       diag(CastExpr->getLocStart(), "redundant cast to the same type")
-          << FixItHint::CreateRemoval(ParenRange);
+          << FixItHint::CreateRemoval(ReplaceRange);
       return;
     }
   }
@@ -136,7 +138,7 @@
                                      getLangOpts()),
           ")");
     }
-    Diag << FixItHint::CreateReplacement(ParenRange, CastText);
+    Diag << FixItHint::CreateReplacement(ReplaceRange, CastText);
   };
   auto ReplaceWithNamedCast = [&](StringRef CastType) {
     Diag << CastType;
diff --git a/clang-tidy/google/CMakeLists.txt b/clang-tidy/google/CMakeLists.txt
index efe3b3c..ff48b63 100644
--- a/clang-tidy/google/CMakeLists.txt
+++ b/clang-tidy/google/CMakeLists.txt
@@ -8,7 +8,6 @@
   GlobalNamesInHeadersCheck.cpp
   GoogleTidyModule.cpp
   IntegerTypesCheck.cpp
-  MemsetZeroLengthCheck.cpp
   NonConstReferences.cpp
   OverloadedUnaryAndCheck.cpp
   StringReferenceMemberCheck.cpp
diff --git a/clang-tidy/google/GlobalNamesInHeadersCheck.cpp b/clang-tidy/google/GlobalNamesInHeadersCheck.cpp
index 71049d9..45c5b70 100644
--- a/clang-tidy/google/GlobalNamesInHeadersCheck.cpp
+++ b/clang-tidy/google/GlobalNamesInHeadersCheck.cpp
@@ -23,8 +23,8 @@
 GlobalNamesInHeadersCheck::GlobalNamesInHeadersCheck(StringRef Name,
                                                      ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
-      RawStringHeaderFileExtensions(
-          Options.getLocalOrGlobal("HeaderFileExtensions", "h")) {
+      RawStringHeaderFileExtensions(Options.getLocalOrGlobal(
+          "HeaderFileExtensions", utils::defaultHeaderFileExtensions())) {
   if (!utils::parseHeaderFileExtensions(RawStringHeaderFileExtensions,
                                         HeaderFileExtensions, ',')) {
     llvm::errs() << "Invalid header file extension: "
diff --git a/clang-tidy/google/GoogleTidyModule.cpp b/clang-tidy/google/GoogleTidyModule.cpp
index e9b4bed..1328463 100644
--- a/clang-tidy/google/GoogleTidyModule.cpp
+++ b/clang-tidy/google/GoogleTidyModule.cpp
@@ -20,7 +20,6 @@
 #include "ExplicitMakePairCheck.h"
 #include "GlobalNamesInHeadersCheck.h"
 #include "IntegerTypesCheck.h"
-#include "MemsetZeroLengthCheck.h"
 #include "NonConstReferences.h"
 #include "OverloadedUnaryAndCheck.h"
 #include "StringReferenceMemberCheck.h"
@@ -55,8 +54,6 @@
         "google-runtime-references");
     CheckFactories.registerCheck<runtime::StringReferenceMemberCheck>(
         "google-runtime-member-string-references");
-    CheckFactories.registerCheck<runtime::MemsetZeroLengthCheck>(
-        "google-runtime-memset");
     CheckFactories.registerCheck<readability::AvoidCStyleCastsCheck>(
         "google-readability-casting");
     CheckFactories.registerCheck<readability::TodoCommentCheck>(
diff --git a/clang-tidy/google/MemsetZeroLengthCheck.cpp b/clang-tidy/google/MemsetZeroLengthCheck.cpp
deleted file mode 100644
index fa87fab..0000000
--- a/clang-tidy/google/MemsetZeroLengthCheck.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-//===--- MemsetZeroLengthCheck.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 "MemsetZeroLengthCheck.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/ASTMatchers/ASTMatchers.h"
-#include "clang/Lex/Lexer.h"
-
-using namespace clang::ast_matchers;
-
-namespace clang {
-namespace tidy {
-namespace google {
-namespace runtime {
-
-void MemsetZeroLengthCheck::registerMatchers(
-    ast_matchers::MatchFinder *Finder) {
-  // Look for memset(x, y, 0) as those is most likely an argument swap.
-  // TODO: Also handle other standard functions that suffer from the same
-  //       problem, e.g. memchr.
-  Finder->addMatcher(callExpr(callee(functionDecl(hasName("::memset"))),
-                              argumentCountIs(3),
-                              unless(isInTemplateInstantiation()))
-                         .bind("decl"),
-                     this);
-}
-
-/// \brief Get a StringRef representing a SourceRange.
-static StringRef getAsString(const MatchFinder::MatchResult &Result,
-                             SourceRange R) {
-  const SourceManager &SM = *Result.SourceManager;
-  // Don't even try to resolve macro or include contraptions. Not worth emitting
-  // a fixit for.
-  if (R.getBegin().isMacroID() ||
-      !SM.isWrittenInSameFile(R.getBegin(), R.getEnd()))
-    return StringRef();
-
-  const char *Begin = SM.getCharacterData(R.getBegin());
-  const char *End = SM.getCharacterData(Lexer::getLocForEndOfToken(
-      R.getEnd(), 0, SM, Result.Context->getLangOpts()));
-
-  return StringRef(Begin, End - Begin);
-}
-
-void MemsetZeroLengthCheck::check(const MatchFinder::MatchResult &Result) {
-  const auto *Call = Result.Nodes.getNodeAs<CallExpr>("decl");
-
-  // Note, this is:
-  // void *memset(void *buffer, int fill_char, size_t byte_count);
-  // Arg1 is fill_char, Arg2 is byte_count.
-  const Expr *Arg1 = Call->getArg(1);
-  const Expr *Arg2 = Call->getArg(2);
-
-  // Return if `byte_count` is not zero at compile time.
-  llvm::APSInt Value1, Value2;
-  if (Arg2->isValueDependent() ||
-      !Arg2->EvaluateAsInt(Value2, *Result.Context) || Value2 != 0)
-    return;
-
-  // Return if `fill_char` is known to be zero or negative at compile
-  // time. In these cases, swapping the args would be a nop, or
-  // introduce a definite bug. The code is likely correct.
-  if (!Arg1->isValueDependent() &&
-      Arg1->EvaluateAsInt(Value1, *Result.Context) &&
-      (Value1 == 0 || Value1.isNegative()))
-    return;
-
-  // `byte_count` is known to be zero at compile time, and `fill_char` is
-  // either not known or known to be a positive integer. Emit a warning
-  // and fix-its to swap the arguments.
-  auto D = diag(Call->getLocStart(),
-                "memset of size zero, potentially swapped arguments");
-  SourceRange LHSRange = Arg1->getSourceRange();
-  SourceRange RHSRange = Arg2->getSourceRange();
-  StringRef RHSString = getAsString(Result, RHSRange);
-  StringRef LHSString = getAsString(Result, LHSRange);
-  if (LHSString.empty() || RHSString.empty())
-    return;
-
-  D << FixItHint::CreateReplacement(CharSourceRange::getTokenRange(LHSRange),
-                                    RHSString)
-    << FixItHint::CreateReplacement(CharSourceRange::getTokenRange(RHSRange),
-                                    LHSString);
-}
-
-} // namespace runtime
-} // namespace google
-} // namespace tidy
-} // namespace clang
diff --git a/clang-tidy/google/MemsetZeroLengthCheck.h b/clang-tidy/google/MemsetZeroLengthCheck.h
deleted file mode 100644
index 57c7aec..0000000
--- a/clang-tidy/google/MemsetZeroLengthCheck.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//===--- MemsetZeroLengthCheck.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_GOOGLE_MEMSETZEROLENGTHCHECK_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_MEMSETZEROLENGTHCHECK_H
-
-#include "../ClangTidy.h"
-
-namespace clang {
-namespace tidy {
-namespace google {
-namespace runtime {
-
-/// Finds calls to memset with a literal zero in the length argument.
-///
-/// This is most likely unintended and the length and value arguments are
-/// swapped.
-///
-/// Corresponding cpplint.py check name: 'runtime/memset'.
-class MemsetZeroLengthCheck : public ClangTidyCheck {
-public:
-  MemsetZeroLengthCheck(StringRef Name, ClangTidyContext *Context)
-      : ClangTidyCheck(Name, Context) {}
-  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
-  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
-};
-
-} // namespace runtime
-} // namespace google
-} // namespace tidy
-} // namespace clang
-
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_MEMSETZEROLENGTHCHECK_H
diff --git a/clang-tidy/google/StringReferenceMemberCheck.cpp b/clang-tidy/google/StringReferenceMemberCheck.cpp
index 36d979b..f3a7bd9 100644
--- a/clang-tidy/google/StringReferenceMemberCheck.cpp
+++ b/clang-tidy/google/StringReferenceMemberCheck.cpp
@@ -27,8 +27,8 @@
     return;
 
   // Look for const references to std::string or ::string.
-  auto String = anyOf(recordDecl(hasName("::std::basic_string")),
-                      recordDecl(hasName("::string")));
+  auto String = anyOf(namedDecl(hasName("::std::string")),
+                      namedDecl(hasName("::string")));
   auto ConstString = qualType(isConstQualified(), hasDeclaration(String));
 
   // Ignore members in template instantiations.
diff --git a/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp b/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp
index 3e76bdb..32ff6e0 100644
--- a/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp
+++ b/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp
@@ -22,8 +22,8 @@
 UnnamedNamespaceInHeaderCheck::UnnamedNamespaceInHeaderCheck(
     StringRef Name, ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
-      RawStringHeaderFileExtensions(
-          Options.getLocalOrGlobal("HeaderFileExtensions", "h,hh,hpp,hxx")) {
+      RawStringHeaderFileExtensions(Options.getLocalOrGlobal(
+          "HeaderFileExtensions", utils::defaultHeaderFileExtensions())) {
   if (!utils::parseHeaderFileExtensions(RawStringHeaderFileExtensions,
                                         HeaderFileExtensions, ',')) {
     llvm::errs() << "Invalid header file extension: "
diff --git a/clang-tidy/hicpp/CMakeLists.txt b/clang-tidy/hicpp/CMakeLists.txt
index d3fff95..fd15d48 100644
--- a/clang-tidy/hicpp/CMakeLists.txt
+++ b/clang-tidy/hicpp/CMakeLists.txt
@@ -1,8 +1,10 @@
 set(LLVM_LINK_COMPONENTS support)
 
 add_clang_library(clangTidyHICPPModule
+  ExceptionBaseclassCheck.cpp
   NoAssemblerCheck.cpp
   HICPPTidyModule.cpp
+  SignedBitwiseCheck.cpp
 
   LINK_LIBS
   clangAST
diff --git a/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp b/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
new file mode 100644
index 0000000..298759f
--- /dev/null
+++ b/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
@@ -0,0 +1,50 @@
+//===--- ExceptionBaseclassCheck.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 "ExceptionBaseclassCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace hicpp {
+
+void ExceptionBaseclassCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  Finder->addMatcher(
+      cxxThrowExpr(allOf(has(expr(unless(hasType(qualType(hasCanonicalType(
+                             hasDeclaration(cxxRecordDecl(isSameOrDerivedFrom(
+                                 hasName("std::exception")))))))))),
+                         has(expr(unless(cxxUnresolvedConstructExpr()))),
+                         eachOf(has(expr(hasType(namedDecl().bind("decl")))),
+                                anything())))
+          .bind("bad_throw"),
+      this);
+}
+
+void ExceptionBaseclassCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *BadThrow = Result.Nodes.getNodeAs<CXXThrowExpr>("bad_throw");
+
+  diag(BadThrow->getSubExpr()->getLocStart(), "throwing an exception whose "
+                                              "type %0 is not derived from "
+                                              "'std::exception'")
+      << BadThrow->getSubExpr()->getType() << BadThrow->getSourceRange();
+
+  const auto *TypeDecl = Result.Nodes.getNodeAs<NamedDecl>("decl");
+  if (TypeDecl != nullptr)
+    diag(TypeDecl->getLocStart(), "type defined here", DiagnosticIDs::Note);
+}
+
+} // namespace hicpp
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/hicpp/ExceptionBaseclassCheck.h b/clang-tidy/hicpp/ExceptionBaseclassCheck.h
new file mode 100644
index 0000000..778979d
--- /dev/null
+++ b/clang-tidy/hicpp/ExceptionBaseclassCheck.h
@@ -0,0 +1,35 @@
+//===--- ExceptionBaseclassCheck.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_HICPP_EXCEPTION_BASECLASS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_HICPP_EXCEPTION_BASECLASS_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace hicpp {
+
+/// Check for thrown exceptions and enforce they are all derived from std::exception.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/hicpp-exception-baseclass.html
+class ExceptionBaseclassCheck : public ClangTidyCheck {
+public:
+  ExceptionBaseclassCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace hicpp
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_HICPP_EXCEPTION_BASECLASS_H
diff --git a/clang-tidy/hicpp/HICPPTidyModule.cpp b/clang-tidy/hicpp/HICPPTidyModule.cpp
index 3cde368..359cd57 100644
--- a/clang-tidy/hicpp/HICPPTidyModule.cpp
+++ b/clang-tidy/hicpp/HICPPTidyModule.cpp
@@ -10,20 +10,33 @@
 #include "../ClangTidy.h"
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
+#include "../cppcoreguidelines/NoMallocCheck.h"
+#include "../cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.h"
 #include "../cppcoreguidelines/ProTypeMemberInitCheck.h"
+#include "../cppcoreguidelines/ProTypeVarargCheck.h"
 #include "../cppcoreguidelines/SpecialMemberFunctionsCheck.h"
 #include "../google/DefaultArgumentsCheck.h"
 #include "../google/ExplicitConstructorCheck.h"
+#include "../misc/MoveConstantArgumentCheck.h"
 #include "../misc/NewDeleteOverloadsCheck.h"
 #include "../misc/NoexceptMoveConstructorCheck.h"
+#include "../misc/StaticAssertCheck.h"
 #include "../misc/UndelegatedConstructor.h"
 #include "../misc/UseAfterMoveCheck.h"
+#include "../modernize/DeprecatedHeadersCheck.h"
+#include "../modernize/UseAutoCheck.h"
+#include "../modernize/UseEmplaceCheck.h"
 #include "../modernize/UseEqualsDefaultCheck.h"
 #include "../modernize/UseEqualsDeleteCheck.h"
+#include "../modernize/UseNoexceptCheck.h"
+#include "../modernize/UseNullptrCheck.h"
 #include "../modernize/UseOverrideCheck.h"
+#include "../readability/BracesAroundStatementsCheck.h"
 #include "../readability/FunctionSizeCheck.h"
 #include "../readability/IdentifierNamingCheck.h"
+#include "ExceptionBaseclassCheck.h"
 #include "NoAssemblerCheck.h"
+#include "SignedBitwiseCheck.h"
 
 namespace clang {
 namespace tidy {
@@ -32,6 +45,14 @@
 class HICPPModule : public ClangTidyModule {
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<readability::BracesAroundStatementsCheck>(
+        "hicpp-braces-around-statements");
+    CheckFactories.registerCheck<modernize::DeprecatedHeadersCheck>(
+        "hicpp-deprecated-headers");
+    CheckFactories.registerCheck<ExceptionBaseclassCheck>(
+        "hicpp-exception-baseclass");
+    CheckFactories.registerCheck<SignedBitwiseCheck>(
+        "hicpp-signed-bitwise");
     CheckFactories.registerCheck<google::ExplicitConstructorCheck>(
         "hicpp-explicit-conversions");
     CheckFactories.registerCheck<readability::FunctionSizeCheck>(
@@ -42,22 +63,40 @@
         "hicpp-invalid-access-moved");
     CheckFactories.registerCheck<cppcoreguidelines::ProTypeMemberInitCheck>(
         "hicpp-member-init");
+    CheckFactories.registerCheck<misc::MoveConstantArgumentCheck>(
+        "hicpp-move-const-arg");
     CheckFactories.registerCheck<misc::NewDeleteOverloadsCheck>(
         "hicpp-new-delete-operators");
     CheckFactories.registerCheck<misc::NoexceptMoveConstructorCheck>(
         "hicpp-noexcept-move");
+    CheckFactories
+        .registerCheck<cppcoreguidelines::ProBoundsArrayToPointerDecayCheck>(
+            "hicpp-no-array-decay");
     CheckFactories.registerCheck<NoAssemblerCheck>("hicpp-no-assembler");
+    CheckFactories.registerCheck<cppcoreguidelines::NoMallocCheck>(
+        "hicpp-no-malloc");
     CheckFactories
         .registerCheck<cppcoreguidelines::SpecialMemberFunctionsCheck>(
             "hicpp-special-member-functions");
+    CheckFactories.registerCheck<misc::StaticAssertCheck>(
+        "hicpp-static-assert");
+    CheckFactories.registerCheck<modernize::UseAutoCheck>("hicpp-use-auto");
     CheckFactories.registerCheck<misc::UndelegatedConstructorCheck>(
         "hicpp-undelegated-constructor");
+    CheckFactories.registerCheck<modernize::UseEmplaceCheck>(
+        "hicpp-use-emplace");
     CheckFactories.registerCheck<modernize::UseEqualsDefaultCheck>(
         "hicpp-use-equals-default");
     CheckFactories.registerCheck<modernize::UseEqualsDeleteCheck>(
         "hicpp-use-equals-delete");
+    CheckFactories.registerCheck<modernize::UseNoexceptCheck>(
+        "hicpp-use-noexcept");
+    CheckFactories.registerCheck<modernize::UseNullptrCheck>(
+        "hicpp-use-nullptr");
     CheckFactories.registerCheck<modernize::UseOverrideCheck>(
         "hicpp-use-override");
+    CheckFactories.registerCheck<cppcoreguidelines::ProTypeVarargCheck>(
+        "hicpp-vararg");
   }
 };
 
diff --git a/clang-tidy/hicpp/SignedBitwiseCheck.cpp b/clang-tidy/hicpp/SignedBitwiseCheck.cpp
new file mode 100644
index 0000000..08aed65
--- /dev/null
+++ b/clang-tidy/hicpp/SignedBitwiseCheck.cpp
@@ -0,0 +1,58 @@
+//===--- SignedBitwiseCheck.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 "SignedBitwiseCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+using namespace clang::ast_matchers::internal;
+
+namespace clang {
+namespace tidy {
+namespace hicpp {
+
+void SignedBitwiseCheck::registerMatchers(MatchFinder *Finder) {
+  const auto SignedIntegerOperand =
+      expr(ignoringImpCasts(hasType(isSignedInteger()))).bind("signed_operand");
+
+  // Match binary bitwise operations on signed integer arguments.
+  Finder->addMatcher(
+      binaryOperator(allOf(anyOf(hasOperatorName("|"), hasOperatorName("&"),
+                                 hasOperatorName("^"), hasOperatorName("<<"),
+                                 hasOperatorName(">>")),
+                           hasEitherOperand(SignedIntegerOperand),
+                           hasLHS(hasType(isInteger())),
+                           hasRHS(hasType(isInteger()))))
+          .bind("binary_signed"),
+      this);
+
+  // Match unary operations on signed integer types.
+  Finder->addMatcher(unaryOperator(allOf(hasOperatorName("~"),
+                                         hasUnaryOperand(SignedIntegerOperand)))
+                         .bind("unary_signed"),
+                     this);
+}
+
+void SignedBitwiseCheck::check(const MatchFinder::MatchResult &Result) {
+  const ast_matchers::BoundNodes &N = Result.Nodes;
+  const auto *SignedBinary = N.getNodeAs<BinaryOperator>("binary_signed");
+  const auto *SignedUnary = N.getNodeAs<UnaryOperator>("unary_signed");
+  const auto *SignedOperand = N.getNodeAs<Expr>("signed_operand");
+
+  const bool IsUnary = SignedUnary != nullptr;
+  diag(IsUnary ? SignedUnary->getLocStart() : SignedBinary->getLocStart(),
+       "use of a signed integer operand with a %select{binary|unary}0 bitwise "
+       "operator")
+      << IsUnary << SignedOperand->getSourceRange();
+}
+
+} // namespace hicpp
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/hicpp/SignedBitwiseCheck.h b/clang-tidy/hicpp/SignedBitwiseCheck.h
new file mode 100644
index 0000000..24338ad
--- /dev/null
+++ b/clang-tidy/hicpp/SignedBitwiseCheck.h
@@ -0,0 +1,36 @@
+//===--- SignedBitwiseCheck.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_HICPP_SIGNED_BITWISE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_HICPP_SIGNED_BITWISE_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace hicpp {
+
+/// This check implements the rule 5.6.1 of the HICPP Standard, which disallows
+/// bitwise operations on signed integer types.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/hicpp-signed-bitwise.html
+class SignedBitwiseCheck : public ClangTidyCheck {
+public:
+  SignedBitwiseCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace hicpp
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_HICPP_SIGNED_BITWISE_H
diff --git a/clang-tidy/llvm/HeaderGuardCheck.cpp b/clang-tidy/llvm/HeaderGuardCheck.cpp
index 6e0c2cb..c0e449e 100644
--- a/clang-tidy/llvm/HeaderGuardCheck.cpp
+++ b/clang-tidy/llvm/HeaderGuardCheck.cpp
@@ -15,20 +15,7 @@
 
 LLVMHeaderGuardCheck::LLVMHeaderGuardCheck(StringRef Name,
                                            ClangTidyContext *Context)
-    : HeaderGuardCheck(Name, Context),
-      RawStringHeaderFileExtensions(
-          Options.getLocalOrGlobal("HeaderFileExtensions", ",h,hh,hpp,hxx")) {
-  utils::parseHeaderFileExtensions(RawStringHeaderFileExtensions,
-                                   HeaderFileExtensions, ',');
-}
-
-void LLVMHeaderGuardCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
-  Options.store(Opts, "HeaderFileExtensions", RawStringHeaderFileExtensions);
-}
-
-bool LLVMHeaderGuardCheck::shouldFixHeaderGuard(StringRef FileName) {
-  return utils::isHeaderFileExtension(FileName, HeaderFileExtensions);
-}
+    : HeaderGuardCheck(Name, Context) {}
 
 std::string LLVMHeaderGuardCheck::getHeaderGuard(StringRef Filename,
                                                  StringRef OldGuard) {
diff --git a/clang-tidy/llvm/HeaderGuardCheck.h b/clang-tidy/llvm/HeaderGuardCheck.h
index 3b8ad2b..ca2d7ef 100644
--- a/clang-tidy/llvm/HeaderGuardCheck.h
+++ b/clang-tidy/llvm/HeaderGuardCheck.h
@@ -29,14 +29,8 @@
 public:
   LLVMHeaderGuardCheck(StringRef Name, ClangTidyContext *Context);
 
-  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
   bool shouldSuggestEndifComment(StringRef Filename) override { return false; }
-  bool shouldFixHeaderGuard(StringRef Filename) override;
   std::string getHeaderGuard(StringRef Filename, StringRef OldGuard) override;
-
-private:
-  std::string RawStringHeaderFileExtensions;
-  utils::HeaderFileExtensionsSet HeaderFileExtensions;
 };
 
 } // namespace llvm
diff --git a/clang-tidy/misc/DanglingHandleCheck.cpp b/clang-tidy/misc/DanglingHandleCheck.cpp
index 67f83d2..86220f4 100644
--- a/clang-tidy/misc/DanglingHandleCheck.cpp
+++ b/clang-tidy/misc/DanglingHandleCheck.cpp
@@ -71,11 +71,13 @@
           // For sequences: assign, push_back, resize.
           cxxMemberCallExpr(
               callee(functionDecl(hasAnyName("assign", "push_back", "resize"))),
-              on(expr(hasType(recordDecl(isASequence()))))),
+              on(expr(hasType(hasUnqualifiedDesugaredType(
+                  recordType(hasDeclaration(recordDecl(isASequence())))))))),
           // For sequences and sets: insert.
-          cxxMemberCallExpr(
-              callee(functionDecl(hasName("insert"))),
-              on(expr(hasType(recordDecl(anyOf(isASequence(), isASet())))))),
+          cxxMemberCallExpr(callee(functionDecl(hasName("insert"))),
+                            on(expr(hasType(hasUnqualifiedDesugaredType(
+                                recordType(hasDeclaration(recordDecl(
+                                    anyOf(isASequence(), isASet()))))))))),
           // For maps: operator[].
           cxxOperatorCallExpr(callee(cxxMethodDecl(ofClass(isAMap()))),
                               hasOverloadedOperatorName("[]"))));
@@ -103,7 +105,8 @@
 
   // Find 'Handle foo(ReturnsAValue());'
   Finder->addMatcher(
-      varDecl(hasType(cxxRecordDecl(IsAHandle)),
+      varDecl(hasType(hasUnqualifiedDesugaredType(
+                  recordType(hasDeclaration(cxxRecordDecl(IsAHandle))))),
               hasInitializer(
                   exprWithCleanups(has(ignoringParenImpCasts(ConvertedHandle)))
                       .bind("bad_stmt"))),
@@ -112,7 +115,9 @@
   // Find 'Handle foo = ReturnsAValue();'
   Finder->addMatcher(
       varDecl(
-          hasType(cxxRecordDecl(IsAHandle)), unless(parmVarDecl()),
+          hasType(hasUnqualifiedDesugaredType(
+              recordType(hasDeclaration(cxxRecordDecl(IsAHandle))))),
+          unless(parmVarDecl()),
           hasInitializer(exprWithCleanups(has(ignoringParenImpCasts(handleFrom(
                                               IsAHandle, ConvertedHandle))))
                              .bind("bad_stmt"))),
@@ -139,13 +144,15 @@
           // We have to match both.
           has(ignoringImplicit(handleFrom(
               IsAHandle,
-              handleFrom(IsAHandle, declRefExpr(to(varDecl(
-                                        // Is function scope ...
-                                        hasAutomaticStorageDuration(),
-                                        // ... and it is a local array or Value.
-                                        anyOf(hasType(arrayType()),
-                                              hasType(recordDecl(
-                                                  unless(IsAHandle))))))))))),
+              handleFrom(IsAHandle,
+                         declRefExpr(to(varDecl(
+                             // Is function scope ...
+                             hasAutomaticStorageDuration(),
+                             // ... and it is a local array or Value.
+                             anyOf(hasType(arrayType()),
+                                   hasType(hasUnqualifiedDesugaredType(
+                                       recordType(hasDeclaration(recordDecl(
+                                           unless(IsAHandle)))))))))))))),
           // Temporary fix for false positives inside lambdas.
           unless(hasAncestor(lambdaExpr())))
           .bind("bad_stmt"),
diff --git a/clang-tidy/misc/DefinitionsInHeadersCheck.cpp b/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
index 39ae7b9..69ef3ef 100644
--- a/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
+++ b/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
@@ -32,8 +32,8 @@
                                                      ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
       UseHeaderFileExtension(Options.get("UseHeaderFileExtension", true)),
-      RawStringHeaderFileExtensions(
-          Options.getLocalOrGlobal("HeaderFileExtensions", ",h,hh,hpp,hxx")) {
+      RawStringHeaderFileExtensions(Options.getLocalOrGlobal(
+          "HeaderFileExtensions", utils::defaultHeaderFileExtensions())) {
   if (!utils::parseHeaderFileExtensions(RawStringHeaderFileExtensions,
                                         HeaderFileExtensions, ',')) {
     // FIXME: Find a more suitable way to handle invalid configuration
@@ -94,7 +94,10 @@
   //
   // Although these might also cause ODR violations, we can be less certain and
   // should try to keep the false-positive rate down.
-  if (ND->getLinkageInternal() == InternalLinkage)
+  //
+  // FIXME: Should declarations in anonymous namespaces get the same treatment
+  // as static / const declarations?
+  if (!ND->hasExternalFormalLinkage() && !ND->isInAnonymousNamespace())
     return;
 
   if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
@@ -139,6 +142,9 @@
     // Ignore variable definition within function scope.
     if (VD->hasLocalStorage() || VD->isStaticLocal())
       return;
+    // Ignore inline variables.
+    if (VD->isInline())
+      return;
 
     diag(VD->getLocation(),
          "variable %0 defined in a header file; "
diff --git a/clang-tidy/misc/InaccurateEraseCheck.cpp b/clang-tidy/misc/InaccurateEraseCheck.cpp
index f75d6fe..fd86d17 100644
--- a/clang-tidy/misc/InaccurateEraseCheck.cpp
+++ b/clang-tidy/misc/InaccurateEraseCheck.cpp
@@ -39,7 +39,8 @@
                     anything())))
           .bind("alg");
 
-  const auto DeclInStd = decl(isInStdNamespace());
+  const auto DeclInStd = type(hasUnqualifiedDesugaredType(
+      tagType(hasDeclaration(decl(isInStdNamespace())))));
   Finder->addMatcher(
       cxxMemberCallExpr(
           on(anyOf(hasType(DeclInStd), hasType(pointsTo(DeclInStd)))),
diff --git a/clang-tidy/misc/MacroParenthesesCheck.cpp b/clang-tidy/misc/MacroParenthesesCheck.cpp
index dd4df1c..59fe772 100644
--- a/clang-tidy/misc/MacroParenthesesCheck.cpp
+++ b/clang-tidy/misc/MacroParenthesesCheck.cpp
@@ -185,7 +185,7 @@
       continue;
 
     // Only interested in macro arguments.
-    if (MI->getArgumentNum(Tok.getIdentifierInfo()) < 0)
+    if (MI->getParameterNum(Tok.getIdentifierInfo()) < 0)
       continue;
 
     // Argument is surrounded with parentheses/squares/braces/commas.
diff --git a/clang-tidy/misc/MacroRepeatedSideEffectsCheck.cpp b/clang-tidy/misc/MacroRepeatedSideEffectsCheck.cpp
index 229ec85..1bbed46 100644
--- a/clang-tidy/misc/MacroRepeatedSideEffectsCheck.cpp
+++ b/clang-tidy/misc/MacroRepeatedSideEffectsCheck.cpp
@@ -58,8 +58,8 @@
           }) != MI->tokens().end())
     return;
 
-  for (unsigned ArgNo = 0U; ArgNo < MI->getNumArgs(); ++ArgNo) {
-    const IdentifierInfo *Arg = *(MI->arg_begin() + ArgNo);
+  for (unsigned ArgNo = 0U; ArgNo < MI->getNumParams(); ++ArgNo) {
+    const IdentifierInfo *Arg = *(MI->param_begin() + ArgNo);
     const Token *ResultArgToks = Args->getUnexpArgument(ArgNo);
 
     if (hasSideEffects(ResultArgToks) &&
diff --git a/clang-tidy/misc/MisplacedWideningCastCheck.cpp b/clang-tidy/misc/MisplacedWideningCastCheck.cpp
index 269004f..2ba38b3 100644
--- a/clang-tidy/misc/MisplacedWideningCastCheck.cpp
+++ b/clang-tidy/misc/MisplacedWideningCastCheck.cpp
@@ -192,6 +192,10 @@
   if (Calc->getLocStart().isMacroID())
     return;
 
+  if (Cast->isTypeDependent() || Cast->isValueDependent() ||
+      Calc->isTypeDependent() || Calc->isValueDependent())
+    return;
+
   ASTContext &Context = *Result.Context;
 
   QualType CastType = Cast->getType();
diff --git a/clang-tidy/misc/MoveConstructorInitCheck.cpp b/clang-tidy/misc/MoveConstructorInitCheck.cpp
index 081c439..2c6af5f 100644
--- a/clang-tidy/misc/MoveConstructorInitCheck.cpp
+++ b/clang-tidy/misc/MoveConstructorInitCheck.cpp
@@ -25,7 +25,7 @@
                                                    ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
       IncludeStyle(utils::IncludeSorter::parseIncludeStyle(
-          Options.get("IncludeStyle", "llvm"))) {}
+          Options.getLocalOrGlobal("IncludeStyle", "llvm"))) {}
 
 void MoveConstructorInitCheck::registerMatchers(MatchFinder *Finder) {
   // Only register the matchers for C++11; the functionality currently does not
diff --git a/clang-tidy/misc/SuspiciousEnumUsageCheck.cpp b/clang-tidy/misc/SuspiciousEnumUsageCheck.cpp
index 501e2b2..416a418 100644
--- a/clang-tidy/misc/SuspiciousEnumUsageCheck.cpp
+++ b/clang-tidy/misc/SuspiciousEnumUsageCheck.cpp
@@ -42,7 +42,8 @@
     const auto MinMaxVal = std::minmax_element(
         EnumDec->enumerator_begin(), EnumDec->enumerator_end(),
         [](const EnumConstantDecl *E1, const EnumConstantDecl *E2) {
-          return E1->getInitVal() < E2->getInitVal();
+          return llvm::APSInt::compareValues(E1->getInitVal(),
+                                             E2->getInitVal()) < 0;
         });
     MinVal = MinMaxVal.first->getInitVal();
     MaxVal = MinMaxVal.second->getInitVal();
@@ -57,7 +58,8 @@
 static bool hasDisjointValueRange(const EnumDecl *Enum1,
                                   const EnumDecl *Enum2) {
   ValueRange Range1(Enum1), Range2(Enum2);
-  return (Range1.MaxVal < Range2.MinVal) || (Range2.MaxVal < Range1.MinVal);
+  return llvm::APSInt::compareValues(Range1.MaxVal, Range2.MinVal) < 0 ||
+         llvm::APSInt::compareValues(Range2.MaxVal, Range1.MinVal) < 0;
 }
 
 static bool isNonPowerOf2NorNullLiteral(const EnumConstantDecl *EnumConst) {
diff --git a/clang-tidy/misc/UnusedParametersCheck.cpp b/clang-tidy/misc/UnusedParametersCheck.cpp
index 07e82f0..03196c8 100644
--- a/clang-tidy/misc/UnusedParametersCheck.cpp
+++ b/clang-tidy/misc/UnusedParametersCheck.cpp
@@ -138,7 +138,7 @@
   if (Function->isExternallyVisible() ||
       !Result.SourceManager->isInMainFile(Function->getLocation()) ||
       !Indexer->getOtherRefs(Function).empty() || isOverrideMethod(Function)) {
-    SourceRange RemovalRange(Param->getLocation(), Param->getLocEnd());
+    SourceRange RemovalRange(Param->getLocation());
     // Note: We always add a space before the '/*' to not accidentally create a
     // '*/*' for pointer types, which doesn't start a comment. clang-format will
     // clean this up afterwards.
diff --git a/clang-tidy/misc/UseAfterMoveCheck.cpp b/clang-tidy/misc/UseAfterMoveCheck.cpp
index 842aa5b..9967376 100644
--- a/clang-tidy/misc/UseAfterMoveCheck.cpp
+++ b/clang-tidy/misc/UseAfterMoveCheck.cpp
@@ -271,15 +271,17 @@
   auto DeclRefMatcher =
       declRefExpr(hasDeclaration(equalsNode(MovedVariable))).bind("declref");
 
-  auto StandardContainerTypeMatcher = hasType(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 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(cxxRecordDecl(
-      hasAnyName("::std::unique_ptr", "::std::shared_ptr", "::std::weak_ptr")));
+  auto StandardSmartPointerTypeMatcher = hasType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(cxxRecordDecl(hasAnyName(
+          "::std::unique_ptr", "::std::shared_ptr", "::std::weak_ptr"))))));
 
   // Matches different types of reinitialization.
   auto ReinitMatcher =
diff --git a/clang-tidy/misc/VirtualNearMissCheck.cpp b/clang-tidy/misc/VirtualNearMissCheck.cpp
index 0435406..fd74bb6 100644
--- a/clang-tidy/misc/VirtualNearMissCheck.cpp
+++ b/clang-tidy/misc/VirtualNearMissCheck.cpp
@@ -244,8 +244,8 @@
         if (isOverriddenByDerivedClass(BaseMD, DerivedRD))
           continue;
 
-        unsigned EditDistance =
-            BaseMD->getName().edit_distance(DerivedMD->getName());
+        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.
diff --git a/clang-tidy/misc/VirtualNearMissCheck.h b/clang-tidy/misc/VirtualNearMissCheck.h
index 4e108f2..3d3b9eb 100644
--- a/clang-tidy/misc/VirtualNearMissCheck.h
+++ b/clang-tidy/misc/VirtualNearMissCheck.h
@@ -11,7 +11,7 @@
 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_VIRTUAL_NEAR_MISS_H
 
 #include "../ClangTidy.h"
-#include <map>
+#include "llvm/ADT/DenseMap.h"
 
 namespace clang {
 namespace tidy {
@@ -47,12 +47,12 @@
 
   /// Key: the unique ID of a method.
   /// Value: whether the method is possible to be overridden.
-  std::map<const CXXMethodDecl *, bool> PossibleMap;
+  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.
-  std::map<std::pair<const CXXMethodDecl *, const CXXRecordDecl *>, bool>
+  llvm::DenseMap<std::pair<const CXXMethodDecl *, const CXXRecordDecl *>, bool>
       OverriddenMap;
 
   const unsigned EditDistanceThreshold = 1;
diff --git a/clang-tidy/modernize/CMakeLists.txt b/clang-tidy/modernize/CMakeLists.txt
index 8058f52..e344ada 100644
--- a/clang-tidy/modernize/CMakeLists.txt
+++ b/clang-tidy/modernize/CMakeLists.txt
@@ -16,6 +16,7 @@
   ReplaceRandomShuffleCheck.cpp
   ReturnBracedInitListCheck.cpp
   ShrinkToFitCheck.cpp
+  UnaryStaticAssertCheck.cpp
   UseAutoCheck.cpp
   UseBoolLiteralsCheck.cpp
   UseDefaultMemberInitCheck.cpp
diff --git a/clang-tidy/modernize/LoopConvertCheck.cpp b/clang-tidy/modernize/LoopConvertCheck.cpp
index ac0bceb..54bf941 100644
--- a/clang-tidy/modernize/LoopConvertCheck.cpp
+++ b/clang-tidy/modernize/LoopConvertCheck.cpp
@@ -161,17 +161,18 @@
   // overloaded operator*(). If the operator*() returns by value instead of by
   // reference then the return type is tagged with DerefByValueResultName.
   internal::Matcher<VarDecl> TestDerefReturnsByValue =
-      hasType(cxxRecordDecl(hasMethod(allOf(
-          hasOverloadedOperatorName("*"),
-          anyOf(
-              // Tag the return type if it's by value.
-              returns(qualType(unless(hasCanonicalType(referenceType())))
-                          .bind(DerefByValueResultName)),
-              returns(
-                  // Skip loops where the iterator's operator* returns an
-                  // rvalue reference. This is just weird.
-                  qualType(unless(hasCanonicalType(rValueReferenceType())))
-                      .bind(DerefByRefResultName)))))));
+      hasType(hasUnqualifiedDesugaredType(
+          recordType(hasDeclaration(cxxRecordDecl(hasMethod(allOf(
+              hasOverloadedOperatorName("*"),
+              anyOf(
+                  // Tag the return type if it's by value.
+                  returns(qualType(unless(hasCanonicalType(referenceType())))
+                              .bind(DerefByValueResultName)),
+                  returns(
+                      // Skip loops where the iterator's operator* returns an
+                      // rvalue reference. This is just weird.
+                      qualType(unless(hasCanonicalType(rValueReferenceType())))
+                          .bind(DerefByRefResultName))))))))));
 
   return forStmt(
              unless(isInTemplateInstantiation()),
@@ -242,16 +243,17 @@
   // functions called begin() and end() taking the container as an argument
   // are also allowed.
   TypeMatcher RecordWithBeginEnd = qualType(anyOf(
-      qualType(isConstQualified(),
-               hasDeclaration(cxxRecordDecl(
-                   hasMethod(cxxMethodDecl(hasName("begin"), isConst())),
-                   hasMethod(cxxMethodDecl(hasName("end"),
-                                           isConst())))) // hasDeclaration
-               ),                                        // qualType
       qualType(
-          unless(isConstQualified()),
-          hasDeclaration(cxxRecordDecl(hasMethod(hasName("begin")),
-                                       hasMethod(hasName("end"))))) // qualType
+          isConstQualified(),
+          hasUnqualifiedDesugaredType(recordType(hasDeclaration(cxxRecordDecl(
+              hasMethod(cxxMethodDecl(hasName("begin"), isConst())),
+              hasMethod(cxxMethodDecl(hasName("end"),
+                                      isConst()))))   // hasDeclaration
+                                                 ))), // qualType
+      qualType(unless(isConstQualified()),
+               hasUnqualifiedDesugaredType(recordType(hasDeclaration(
+                   cxxRecordDecl(hasMethod(hasName("begin")),
+                                 hasMethod(hasName("end"))))))) // qualType
       ));
 
   StatementMatcher SizeCallMatcher = cxxMemberCallExpr(
diff --git a/clang-tidy/modernize/MakeSharedCheck.cpp b/clang-tidy/modernize/MakeSharedCheck.cpp
index 0495dca..541c2cb 100644
--- a/clang-tidy/modernize/MakeSharedCheck.cpp
+++ b/clang-tidy/modernize/MakeSharedCheck.cpp
@@ -20,10 +20,11 @@
 
 MakeSharedCheck::SmartPtrTypeMatcher
 MakeSharedCheck::getSmartPointerTypeMatcher() const {
-  return qualType(hasDeclaration(classTemplateSpecializationDecl(
-      hasName("::std::shared_ptr"), templateArgumentCountIs(1),
-      hasTemplateArgument(
-          0, templateArgument(refersToType(qualType().bind(PointerType)))))));
+  return qualType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(classTemplateSpecializationDecl(
+          hasName("::std::shared_ptr"), templateArgumentCountIs(1),
+          hasTemplateArgument(0, templateArgument(refersToType(
+                                     qualType().bind(PointerType)))))))));
 }
 
 } // namespace modernize
diff --git a/clang-tidy/modernize/MakeSmartPtrCheck.cpp b/clang-tidy/modernize/MakeSmartPtrCheck.cpp
index d032588..8f350ae 100644
--- a/clang-tidy/modernize/MakeSmartPtrCheck.cpp
+++ b/clang-tidy/modernize/MakeSmartPtrCheck.cpp
@@ -8,7 +8,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "MakeSharedCheck.h"
+#include "clang/Frontend/CompilerInstance.h"
 #include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
 
 using namespace clang::ast_matchers;
 
@@ -16,15 +18,56 @@
 namespace tidy {
 namespace modernize {
 
+namespace {
+
+constexpr char StdMemoryHeader[] = "memory";
+
+std::string GetNewExprName(const CXXNewExpr *NewExpr,
+                           const SourceManager &SM,
+                           const LangOptions &Lang) {
+  StringRef WrittenName = Lexer::getSourceText(
+      CharSourceRange::getTokenRange(
+          NewExpr->getAllocatedTypeSourceInfo()->getTypeLoc().getSourceRange()),
+      SM, Lang);
+  if (NewExpr->isArray()) {
+    return WrittenName.str() + "[]";
+  }
+  return WrittenName.str();
+}
+
+} // namespace
+
 const char MakeSmartPtrCheck::PointerType[] = "pointerType";
 const char MakeSmartPtrCheck::ConstructorCall[] = "constructorCall";
 const char MakeSmartPtrCheck::ResetCall[] = "resetCall";
 const char MakeSmartPtrCheck::NewExpression[] = "newExpression";
 
-MakeSmartPtrCheck::MakeSmartPtrCheck(StringRef Name, ClangTidyContext *Context,
-                                     std::string makeSmartPtrFunctionName)
+MakeSmartPtrCheck::MakeSmartPtrCheck(StringRef Name,
+                                     ClangTidyContext* Context,
+                                     StringRef MakeSmartPtrFunctionName)
     : ClangTidyCheck(Name, Context),
-      makeSmartPtrFunctionName(std::move(makeSmartPtrFunctionName)) {}
+      IncludeStyle(utils::IncludeSorter::parseIncludeStyle(
+          Options.getLocalOrGlobal("IncludeStyle", "llvm"))),
+      MakeSmartPtrFunctionHeader(
+          Options.get("MakeSmartPtrFunctionHeader", StdMemoryHeader)),
+      MakeSmartPtrFunctionName(
+          Options.get("MakeSmartPtrFunction", MakeSmartPtrFunctionName)),
+      IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true)) {}
+
+void MakeSmartPtrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IncludeStyle", IncludeStyle);
+  Options.store(Opts, "MakeSmartPtrFunctionHeader", MakeSmartPtrFunctionHeader);
+  Options.store(Opts, "MakeSmartPtrFunction", MakeSmartPtrFunctionName);
+  Options.store(Opts, "IgnoreMacros", IgnoreMacros);
+}
+
+void MakeSmartPtrCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+  if (getLangOpts().CPlusPlus11) {
+    Inserter.reset(new utils::IncludeInserter(
+        Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle));
+    Compiler.getPreprocessor().addPPCallbacks(Inserter->CreatePPCallbacks());
+  }
+}
 
 void MakeSmartPtrCheck::registerMatchers(ast_matchers::MatchFinder *Finder) {
   if (!getLangOpts().CPlusPlus11)
@@ -43,7 +86,8 @@
                           cxxNewExpr(hasType(pointsTo(qualType(hasCanonicalType(
                                          equalsBoundNode(PointerType))))),
                                      CanCallCtor)
-                              .bind(NewExpression)))
+                              .bind(NewExpression)),
+              unless(isInTemplateInstantiation()))
               .bind(ConstructorCall)))),
       this);
 
@@ -51,7 +95,8 @@
       cxxMemberCallExpr(
           thisPointerType(getSmartPointerTypeMatcher()),
           callee(cxxMethodDecl(hasName("reset"))),
-          hasArgument(0, cxxNewExpr(CanCallCtor).bind(NewExpression)))
+          hasArgument(0, cxxNewExpr(CanCallCtor).bind(NewExpression)),
+          unless(isInTemplateInstantiation()))
           .bind(ResetCall),
       this);
 }
@@ -82,17 +127,31 @@
                                        const QualType *Type,
                                        const CXXNewExpr *New) {
   SourceLocation ConstructCallStart = Construct->getExprLoc();
+  bool InMacro = ConstructCallStart.isMacroID();
+
+  if (InMacro && IgnoreMacros) {
+    return;
+  }
 
   bool Invalid = false;
   StringRef ExprStr = Lexer::getSourceText(
       CharSourceRange::getCharRange(
           ConstructCallStart, Construct->getParenOrBraceRange().getBegin()),
-      SM, LangOptions(), &Invalid);
+      SM, getLangOpts(), &Invalid);
   if (Invalid)
     return;
 
   auto Diag = diag(ConstructCallStart, "use %0 instead")
-              << makeSmartPtrFunctionName;
+              << MakeSmartPtrFunctionName;
+
+  // Disable the fix in macros.
+  if (InMacro) {
+    return;
+  }
+
+  if (!replaceNew(Diag, New, SM)) {
+    return;
+  }
 
   // Find the location of the template's left angle.
   size_t LAngle = ExprStr.find("<");
@@ -102,14 +161,15 @@
     // we have to add it back.
     ConstructCallEnd = ConstructCallStart.getLocWithOffset(ExprStr.size());
     Diag << FixItHint::CreateInsertion(
-        ConstructCallEnd, "<" + Type->getAsString(getLangOpts()) + ">");
+        ConstructCallEnd,
+        "<" + GetNewExprName(New, SM, getLangOpts()) + ">");
   } else {
     ConstructCallEnd = ConstructCallStart.getLocWithOffset(LAngle);
   }
 
   Diag << FixItHint::CreateReplacement(
       CharSourceRange::getCharRange(ConstructCallStart, ConstructCallEnd),
-      makeSmartPtrFunctionName);
+      MakeSmartPtrFunctionName);
 
   // If the smart_ptr is built with brace enclosed direct initialization, use
   // parenthesis instead.
@@ -125,7 +185,7 @@
         ")");
   }
 
-  replaceNew(Diag, New);
+  insertHeader(Diag, SM.getFileID(ConstructCallStart));
 }
 
 void MakeSmartPtrCheck::checkReset(SourceManager &SM,
@@ -138,51 +198,141 @@
   SourceLocation ExprEnd =
       Lexer::getLocForEndOfToken(Expr->getLocEnd(), 0, SM, getLangOpts());
 
+  bool InMacro = ExprStart.isMacroID();
+
+  if (InMacro && IgnoreMacros) {
+    return;
+  }
+
+  // There are some cases where we don't have operator ("." or "->") of the
+  // "reset" expression, e.g. call "reset()" method directly in the subclass of
+  // "std::unique_ptr<>". We skip these cases.
+  if (OperatorLoc.isInvalid()) {
+    return;
+  }
+
   auto Diag = diag(ResetCallStart, "use %0 instead")
-              << makeSmartPtrFunctionName;
+              << MakeSmartPtrFunctionName;
+
+  // Disable the fix in macros.
+  if (InMacro) {
+    return;
+  }
+
+  if (!replaceNew(Diag, New, SM)) {
+    return;
+  }
 
   Diag << FixItHint::CreateReplacement(
       CharSourceRange::getCharRange(OperatorLoc, ExprEnd),
-      (llvm::Twine(" = ") + makeSmartPtrFunctionName + "<" +
-       New->getAllocatedType().getAsString(getLangOpts()) + ">")
+      (llvm::Twine(" = ") + MakeSmartPtrFunctionName + "<" +
+       GetNewExprName(New, SM, getLangOpts()) + ">")
           .str());
 
   if (Expr->isArrow())
     Diag << FixItHint::CreateInsertion(ExprStart, "*");
 
-  replaceNew(Diag, New);
+  insertHeader(Diag, SM.getFileID(OperatorLoc));
 }
 
-void MakeSmartPtrCheck::replaceNew(DiagnosticBuilder &Diag,
-                                   const CXXNewExpr *New) {
+bool MakeSmartPtrCheck::replaceNew(DiagnosticBuilder &Diag,
+                                   const CXXNewExpr *New,
+                                   SourceManager& SM) {
   SourceLocation NewStart = New->getSourceRange().getBegin();
   SourceLocation NewEnd = New->getSourceRange().getEnd();
+
+  std::string ArraySizeExpr;
+  if (const auto* ArraySize = New->getArraySize()) {
+    ArraySizeExpr = Lexer::getSourceText(CharSourceRange::getTokenRange(
+                                             ArraySize->getSourceRange()),
+                                         SM, getLangOpts())
+                        .str();
+  }
+
   switch (New->getInitializationStyle()) {
   case CXXNewExpr::NoInit: {
-    Diag << FixItHint::CreateRemoval(SourceRange(NewStart, NewEnd));
+    if (ArraySizeExpr.empty()) {
+      Diag << FixItHint::CreateRemoval(SourceRange(NewStart, NewEnd));
+    } else {
+      // New array expression without written initializer:
+      //   smart_ptr<Foo[]>(new Foo[5]);
+      Diag << FixItHint::CreateReplacement(SourceRange(NewStart, NewEnd),
+                                           ArraySizeExpr);
+    }
     break;
   }
   case CXXNewExpr::CallInit: {
-    SourceRange InitRange = New->getDirectInitRange();
-    Diag << FixItHint::CreateRemoval(
-        SourceRange(NewStart, InitRange.getBegin()));
-    Diag << FixItHint::CreateRemoval(SourceRange(InitRange.getEnd(), NewEnd));
+    // FIXME: Add fixes for constructors with parameters that can be created
+    // with a C++11 braced-init-list (e.g. std::vector, std::map).
+    // Unlike ordinal cases, braced list can not be deduced in
+    // std::make_smart_ptr, we need to specify the type explicitly in the fixes:
+    //   struct S { S(std::initializer_list<int>, int); };
+    //   struct S2 { S2(std::vector<int>); };
+    //   smart_ptr<S>(new S({1, 2, 3}, 1));  // C++98 call-style initialization
+    //   smart_ptr<S>(new S({}, 1));
+    //   smart_ptr<S2>(new S2({1})); // implicit conversion:
+    //                               //   std::initializer_list => std::vector
+    // The above samples have to be replaced with:
+    //   std::make_smart_ptr<S>(std::initializer_list<int>({1, 2, 3}), 1);
+    //   std::make_smart_ptr<S>(std::initializer_list<int>({}), 1);
+    //   std::make_smart_ptr<S2>(std::vector<int>({1}));
+    if (const auto *CE = New->getConstructExpr()) {
+      for (const auto *Arg : CE->arguments()) {
+        if (isa<CXXStdInitializerListExpr>(Arg)) {
+          return false;
+        }
+        // Check the implicit conversion from the std::initializer_list type to
+        // a class type.
+        if (const auto *ImplicitCE = dyn_cast<CXXConstructExpr>(Arg)) {
+          if (ImplicitCE->isStdInitListInitialization()) {
+            return false;
+          }
+        }
+      }
+    }
+    if (ArraySizeExpr.empty()) {
+      SourceRange InitRange = New->getDirectInitRange();
+      Diag << FixItHint::CreateRemoval(
+          SourceRange(NewStart, InitRange.getBegin()));
+      Diag << FixItHint::CreateRemoval(SourceRange(InitRange.getEnd(), NewEnd));
+    }
+    else {
+      // New array expression with default/value initialization:
+      //   smart_ptr<Foo[]>(new int[5]());
+      //   smart_ptr<Foo[]>(new Foo[5]());
+      Diag << FixItHint::CreateReplacement(SourceRange(NewStart, NewEnd),
+                                           ArraySizeExpr);
+    }
     break;
   }
   case CXXNewExpr::ListInit: {
     // Range of the substring that we do not want to remove.
     SourceRange InitRange;
     if (const auto *NewConstruct = New->getConstructExpr()) {
-      // Direct initialization with initialization list.
-      //   struct S { S(int x) {} };
-      //   smart_ptr<S>(new S{5});
-      // The arguments in the initialization list are going to be forwarded to
-      // the constructor, so this has to be replaced with:
-      //   struct S { S(int x) {} };
-      //   std::make_smart_ptr<S>(5);
-      InitRange = SourceRange(
-          NewConstruct->getParenOrBraceRange().getBegin().getLocWithOffset(1),
-          NewConstruct->getParenOrBraceRange().getEnd().getLocWithOffset(-1));
+      if (NewConstruct->isStdInitListInitialization()) {
+        // FIXME: Add fixes for direct initialization with the initializer-list
+        // constructor. Similar to the above CallInit case, the type has to be
+        // specified explicitly in the fixes.
+        //   struct S { S(std::initializer_list<int>); };
+        //   smart_ptr<S>(new S{1, 2, 3});  // C++11 direct list-initialization
+        //   smart_ptr<S>(new S{});  // use initializer-list consturctor
+        // The above cases have to be replaced with:
+        //   std::make_smart_ptr<S>(std::initializer_list<int>({1, 2, 3}));
+        //   std::make_smart_ptr<S>(std::initializer_list<int>({}));
+        return false;
+      } else {
+        // Direct initialization with ordinary constructors.
+        //   struct S { S(int x); S(); };
+        //   smart_ptr<S>(new S{5});
+        //   smart_ptr<S>(new S{}); // use default constructor
+        // The arguments in the initialization list are going to be forwarded to
+        // the constructor, so this has to be replaced with:
+        //   std::make_smart_ptr<S>(5);
+        //   std::make_smart_ptr<S>();
+        InitRange = SourceRange(
+            NewConstruct->getParenOrBraceRange().getBegin().getLocWithOffset(1),
+            NewConstruct->getParenOrBraceRange().getEnd().getLocWithOffset(-1));
+      }
     } else {
       // Aggregate initialization.
       //   smart_ptr<Pair>(new Pair{first, second});
@@ -199,6 +349,18 @@
     break;
   }
   }
+  return true;
+}
+
+void MakeSmartPtrCheck::insertHeader(DiagnosticBuilder &Diag, FileID FD) {
+  if (MakeSmartPtrFunctionHeader.empty()) {
+    return;
+  }
+  if (auto IncludeFixit = Inserter->CreateIncludeInsertion(
+          FD, MakeSmartPtrFunctionHeader,
+          /*IsAngled=*/MakeSmartPtrFunctionHeader == StdMemoryHeader)) {
+    Diag << *IncludeFixit;
+  }
 }
 
 } // namespace modernize
diff --git a/clang-tidy/modernize/MakeSmartPtrCheck.h b/clang-tidy/modernize/MakeSmartPtrCheck.h
index 87352e2..8282154 100644
--- a/clang-tidy/modernize/MakeSmartPtrCheck.h
+++ b/clang-tidy/modernize/MakeSmartPtrCheck.h
@@ -11,6 +11,7 @@
 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_MAKE_SMART_PTR_H
 
 #include "../ClangTidy.h"
+#include "../utils/IncludeInserter.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchersInternal.h"
 #include "llvm/ADT/StringRef.h"
@@ -24,9 +25,11 @@
 class MakeSmartPtrCheck : public ClangTidyCheck {
 public:
   MakeSmartPtrCheck(StringRef Name, ClangTidyContext *Context,
-                    std::string makeSmartPtrFunctionName);
+                    StringRef MakeSmartPtrFunctionName);
   void registerMatchers(ast_matchers::MatchFinder *Finder) final;
+  void registerPPCallbacks(clang::CompilerInstance &Compiler) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) final;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
 
 protected:
   using SmartPtrTypeMatcher = ast_matchers::internal::BindableMatcher<QualType>;
@@ -43,13 +46,21 @@
   static const char NewExpression[];
 
 private:
-  std::string makeSmartPtrFunctionName;
+  std::unique_ptr<utils::IncludeInserter> Inserter;
+  const utils::IncludeSorter::IncludeStyle IncludeStyle;
+  const std::string MakeSmartPtrFunctionHeader;
+  const std::string MakeSmartPtrFunctionName;
+  const bool IgnoreMacros;
 
   void checkConstruct(SourceManager &SM, const CXXConstructExpr *Construct,
                       const QualType *Type, const CXXNewExpr *New);
   void checkReset(SourceManager &SM, const CXXMemberCallExpr *Member,
                   const CXXNewExpr *New);
-  void replaceNew(DiagnosticBuilder &Diag, const CXXNewExpr *New);
+
+  /// Returns true when the fixes for replacing CXXNewExpr are generated.
+  bool replaceNew(DiagnosticBuilder &Diag, const CXXNewExpr *New,
+                  SourceManager &SM);
+  void insertHeader(DiagnosticBuilder &Diag, FileID FD);
 };
 
 } // namespace modernize
diff --git a/clang-tidy/modernize/MakeUniqueCheck.cpp b/clang-tidy/modernize/MakeUniqueCheck.cpp
index fea452f..4a9b306 100644
--- a/clang-tidy/modernize/MakeUniqueCheck.cpp
+++ b/clang-tidy/modernize/MakeUniqueCheck.cpp
@@ -21,18 +21,19 @@
 
 MakeUniqueCheck::SmartPtrTypeMatcher
 MakeUniqueCheck::getSmartPointerTypeMatcher() const {
-  return qualType(hasDeclaration(classTemplateSpecializationDecl(
-      hasName("::std::unique_ptr"), templateArgumentCountIs(2),
-      hasTemplateArgument(
-          0, templateArgument(refersToType(qualType().bind(PointerType)))),
-      hasTemplateArgument(
-          1,
-          templateArgument(refersToType(
-              qualType(hasDeclaration(classTemplateSpecializationDecl(
-                  hasName("::std::default_delete"), templateArgumentCountIs(1),
-                  hasTemplateArgument(
-                      0, templateArgument(refersToType(
-                             qualType(equalsBoundNode(PointerType))))))))))))));
+  return qualType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(classTemplateSpecializationDecl(
+          hasName("::std::unique_ptr"), templateArgumentCountIs(2),
+          hasTemplateArgument(
+              0, templateArgument(refersToType(qualType().bind(PointerType)))),
+          hasTemplateArgument(
+              1, templateArgument(refersToType(
+                     qualType(hasDeclaration(classTemplateSpecializationDecl(
+                         hasName("::std::default_delete"),
+                         templateArgumentCountIs(1),
+                         hasTemplateArgument(
+                             0, templateArgument(refersToType(qualType(
+                                    equalsBoundNode(PointerType))))))))))))))));
 }
 
 } // namespace modernize
diff --git a/clang-tidy/modernize/ModernizeTidyModule.cpp b/clang-tidy/modernize/ModernizeTidyModule.cpp
index f8c50e0..a2f05d6 100644
--- a/clang-tidy/modernize/ModernizeTidyModule.cpp
+++ b/clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -22,6 +22,7 @@
 #include "ReplaceRandomShuffleCheck.h"
 #include "ReturnBracedInitListCheck.h"
 #include "ShrinkToFitCheck.h"
+#include "UnaryStaticAssertCheck.h"
 #include "UseAutoCheck.h"
 #include "UseBoolLiteralsCheck.h"
 #include "UseDefaultMemberInitCheck.h"
@@ -61,6 +62,8 @@
     CheckFactories.registerCheck<ReturnBracedInitListCheck>(
         "modernize-return-braced-init-list");
     CheckFactories.registerCheck<ShrinkToFitCheck>("modernize-shrink-to-fit");
+    CheckFactories.registerCheck<UnaryStaticAssertCheck>(
+        "modernize-unary-static-assert");
     CheckFactories.registerCheck<UseAutoCheck>("modernize-use-auto");
     CheckFactories.registerCheck<UseBoolLiteralsCheck>(
         "modernize-use-bool-literals");
diff --git a/clang-tidy/modernize/PassByValueCheck.cpp b/clang-tidy/modernize/PassByValueCheck.cpp
index 2d462db..0f4d300 100644
--- a/clang-tidy/modernize/PassByValueCheck.cpp
+++ b/clang-tidy/modernize/PassByValueCheck.cpp
@@ -119,7 +119,7 @@
 PassByValueCheck::PassByValueCheck(StringRef Name, ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
       IncludeStyle(utils::IncludeSorter::parseIncludeStyle(
-          Options.get("IncludeStyle", "llvm"))),
+          Options.getLocalOrGlobal("IncludeStyle", "llvm"))),
       ValuesOnly(Options.get("ValuesOnly", 0) != 0) {}
 
 void PassByValueCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
diff --git a/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp b/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
index 969a55b..c4b371f 100644
--- a/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
+++ b/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
@@ -73,7 +73,7 @@
                                          ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
       IncludeStyle(utils::IncludeSorter::parseIncludeStyle(
-          Options.get("IncludeStyle", "llvm"))) {}
+          Options.getLocalOrGlobal("IncludeStyle", "llvm"))) {}
 
 void ReplaceAutoPtrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
   Options.store(Opts, "IncludeStyle",
diff --git a/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp b/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp
index 909a171..cd9aa11 100644
--- a/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp
+++ b/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp
@@ -25,7 +25,7 @@
                                                      ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
       IncludeStyle(utils::IncludeSorter::parseIncludeStyle(
-          Options.get("IncludeStyle", "llvm"))) {}
+          Options.getLocalOrGlobal("IncludeStyle", "llvm"))) {}
 
 void ReplaceRandomShuffleCheck::registerMatchers(MatchFinder *Finder) {
   if (!getLangOpts().CPlusPlus11)
diff --git a/clang-tidy/modernize/UnaryStaticAssertCheck.cpp b/clang-tidy/modernize/UnaryStaticAssertCheck.cpp
new file mode 100644
index 0000000..c2129e3
--- /dev/null
+++ b/clang-tidy/modernize/UnaryStaticAssertCheck.cpp
@@ -0,0 +1,45 @@
+//===--- UnaryStaticAssertCheck.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 "UnaryStaticAssertCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+void UnaryStaticAssertCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus1z)
+    return;
+
+  Finder->addMatcher(staticAssertDecl().bind("static_assert"), this);
+}
+
+void UnaryStaticAssertCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MatchedDecl =
+      Result.Nodes.getNodeAs<StaticAssertDecl>("static_assert");
+  const StringLiteral *AssertMessage = MatchedDecl->getMessage();
+
+  SourceLocation Loc = MatchedDecl->getLocation();
+
+  if (!AssertMessage || AssertMessage->getLength() ||
+      AssertMessage->getLocStart().isMacroID() || Loc.isMacroID())
+    return;
+
+  diag(Loc,
+       "use unary 'static_assert' when the string literal is an empty string")
+      << FixItHint::CreateRemoval(AssertMessage->getSourceRange());
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/modernize/UnaryStaticAssertCheck.h b/clang-tidy/modernize/UnaryStaticAssertCheck.h
new file mode 100644
index 0000000..b83c2c4
--- /dev/null
+++ b/clang-tidy/modernize/UnaryStaticAssertCheck.h
@@ -0,0 +1,36 @@
+//===--- UnaryStaticAssertCheck.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_MODERNIZE_UNARY_STATIC_ASSERT_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_UNARY_STATIC_ASSERT_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// Replaces a static_assert declaration with an empty message
+/// with the unary version.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-unary-static-assert.html
+class UnaryStaticAssertCheck : public ClangTidyCheck {
+public:
+  UnaryStaticAssertCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_UNARY_STATIC_ASSERT_H
diff --git a/clang-tidy/modernize/UseBoolLiteralsCheck.cpp b/clang-tidy/modernize/UseBoolLiteralsCheck.cpp
index 193bb61..ece8cd5 100644
--- a/clang-tidy/modernize/UseBoolLiteralsCheck.cpp
+++ b/clang-tidy/modernize/UseBoolLiteralsCheck.cpp
@@ -18,6 +18,11 @@
 namespace tidy {
 namespace modernize {
 
+UseBoolLiteralsCheck::UseBoolLiteralsCheck(StringRef Name,
+                                           ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true)) {}
+
 void UseBoolLiteralsCheck::registerMatchers(MatchFinder *Finder) {
   if (!getLangOpts().CPlusPlus)
     return;
@@ -52,11 +57,16 @@
 
   const Expr *Expression = Cast ? Cast : Literal;
 
+  bool InMacro = Expression->getLocStart().isMacroID();
+
+  if (InMacro && IgnoreMacros)
+    return;
+
   auto Diag =
       diag(Expression->getExprLoc(),
            "converting integer literal to bool, use bool literal instead");
 
-  if (!Expression->getLocStart().isMacroID())
+  if (!InMacro)
     Diag << FixItHint::CreateReplacement(
         Expression->getSourceRange(), LiteralBooleanValue ? "true" : "false");
 }
diff --git a/clang-tidy/modernize/UseBoolLiteralsCheck.h b/clang-tidy/modernize/UseBoolLiteralsCheck.h
index 46d7879..c9c7363 100644
--- a/clang-tidy/modernize/UseBoolLiteralsCheck.h
+++ b/clang-tidy/modernize/UseBoolLiteralsCheck.h
@@ -22,10 +22,12 @@
 /// http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-bool-literals.html
 class UseBoolLiteralsCheck : public ClangTidyCheck {
 public:
-  UseBoolLiteralsCheck(StringRef Name, ClangTidyContext *Context)
-      : ClangTidyCheck(Name, Context) {}
+  UseBoolLiteralsCheck(StringRef Name, ClangTidyContext *Context);
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  const bool IgnoreMacros;
 };
 
 } // namespace modernize
diff --git a/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp b/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp
index 7fa773c..b07f730 100644
--- a/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp
+++ b/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp
@@ -140,7 +140,7 @@
                                                      ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
       UseAssignment(Options.get("UseAssignment", 0) != 0),
-      IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", 1) != 0) {}
+      IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true) != 0) {}
 
 void UseDefaultMemberInitCheck::storeOptions(
     ClangTidyOptions::OptionMap &Opts) {
@@ -166,21 +166,22 @@
       cxxConstructorDecl(
           isDefaultConstructor(), unless(isInstantiated()),
           forEachConstructorInitializer(
-              allOf(forField(unless(anyOf(isBitField(),
-                                          hasInClassInitializer(anything())))),
-                    cxxCtorInitializer(isWritten(),
-                                       withInitializer(ignoringImplicit(Init)))
-                        .bind("default")))),
+              cxxCtorInitializer(
+                  forField(unless(anyOf(isBitField(),
+                                        hasInClassInitializer(anything()),
+                                        hasParent(recordDecl(isUnion()))))),
+                  isWritten(), withInitializer(ignoringImplicit(Init)))
+                  .bind("default"))),
       this);
 
   Finder->addMatcher(
       cxxConstructorDecl(
           unless(ast_matchers::isTemplateInstantiation()),
           forEachConstructorInitializer(
-              allOf(forField(hasInClassInitializer(anything())),
-                    cxxCtorInitializer(isWritten(),
-                                       withInitializer(ignoringImplicit(Init)))
-                        .bind("existing")))),
+              cxxCtorInitializer(forField(hasInClassInitializer(anything())),
+                                 isWritten(),
+                                 withInitializer(ignoringImplicit(Init)))
+                  .bind("existing"))),
       this);
 }
 
@@ -197,7 +198,7 @@
 
 void UseDefaultMemberInitCheck::checkDefaultInit(
     const MatchFinder::MatchResult &Result, const CXXCtorInitializer *Init) {
-  const FieldDecl *Field = Init->getMember();
+  const FieldDecl *Field = Init->getAnyMember();
 
   SourceLocation StartLoc = Field->getLocStart();
   if (StartLoc.isMacroID() && IgnoreMacros)
diff --git a/clang-tidy/modernize/UseEmplaceCheck.cpp b/clang-tidy/modernize/UseEmplaceCheck.cpp
index 48fbbfc..4d5d801 100644
--- a/clang-tidy/modernize/UseEmplaceCheck.cpp
+++ b/clang-tidy/modernize/UseEmplaceCheck.cpp
@@ -30,6 +30,7 @@
 
 UseEmplaceCheck::UseEmplaceCheck(StringRef Name, ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
+      IgnoreImplicitConstructors(Options.get("IgnoreImplicitConstructors", 0)),
       ContainersWithPushBack(utils::options::parseStringList(Options.get(
           "ContainersWithPushBack", DefaultContainersWithPushBack))),
       SmartPointers(utils::options::parseStringList(
@@ -120,9 +121,13 @@
 
 void UseEmplaceCheck::check(const MatchFinder::MatchResult &Result) {
   const auto *Call = Result.Nodes.getNodeAs<CXXMemberCallExpr>("call");
-  const auto *InnerCtorCall = Result.Nodes.getNodeAs<CXXConstructExpr>("ctor");
+  const auto *CtorCall = Result.Nodes.getNodeAs<CXXConstructExpr>("ctor");
   const auto *MakeCall = Result.Nodes.getNodeAs<CallExpr>("make");
-  assert((InnerCtorCall || MakeCall) && "No push_back parameter matched");
+  assert((CtorCall || MakeCall) && "No push_back parameter matched");
+
+  if (IgnoreImplicitConstructors && CtorCall && CtorCall->getNumArgs() >= 1 &&
+      CtorCall->getArg(0)->getSourceRange() == CtorCall->getSourceRange())
+    return;
 
   const auto FunctionNameSourceRange = CharSourceRange::getCharRange(
       Call->getExprLoc(), Call->getArg(0)->getExprLoc());
@@ -138,14 +143,14 @@
   const SourceRange CallParensRange =
       MakeCall ? SourceRange(MakeCall->getCallee()->getLocEnd(),
                              MakeCall->getRParenLoc())
-               : InnerCtorCall->getParenOrBraceRange();
+               : CtorCall->getParenOrBraceRange();
 
   // Finish if there is no explicit constructor call.
   if (CallParensRange.getBegin().isInvalid())
     return;
 
   const SourceLocation ExprBegin =
-      MakeCall ? MakeCall->getExprLoc() : InnerCtorCall->getExprLoc();
+      MakeCall ? MakeCall->getExprLoc() : CtorCall->getExprLoc();
 
   // Range for constructor name and opening brace.
   const auto ParamCallSourceRange =
diff --git a/clang-tidy/modernize/UseEmplaceCheck.h b/clang-tidy/modernize/UseEmplaceCheck.h
index 5bd0d8e..2efb212 100644
--- a/clang-tidy/modernize/UseEmplaceCheck.h
+++ b/clang-tidy/modernize/UseEmplaceCheck.h
@@ -33,10 +33,11 @@
   void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
 
 private:
-  std::vector<std::string> ContainersWithPushBack;
-  std::vector<std::string> SmartPointers;
-  std::vector<std::string> TupleTypes;
-  std::vector<std::string> TupleMakeFunctions;
+  const bool IgnoreImplicitConstructors;
+  const std::vector<std::string> ContainersWithPushBack;
+  const std::vector<std::string> SmartPointers;
+  const std::vector<std::string> TupleTypes;
+  const std::vector<std::string> TupleMakeFunctions;
 };
 
 } // namespace modernize
diff --git a/clang-tidy/modernize/UseEqualsDefaultCheck.cpp b/clang-tidy/modernize/UseEqualsDefaultCheck.cpp
index 1b67714..da71624 100644
--- a/clang-tidy/modernize/UseEqualsDefaultCheck.cpp
+++ b/clang-tidy/modernize/UseEqualsDefaultCheck.cpp
@@ -197,36 +197,46 @@
   return !Invalid && std::strspn(Text.data(), " \t\r\n") == Text.size();
 }
 
+UseEqualsDefaultCheck::UseEqualsDefaultCheck(StringRef Name,
+                                             ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true) != 0) {}
+
+void UseEqualsDefaultCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IgnoreMacros", IgnoreMacros);
+}
+
 void UseEqualsDefaultCheck::registerMatchers(MatchFinder *Finder) {
-  if (getLangOpts().CPlusPlus) {
-    // Destructor.
-    Finder->addMatcher(cxxDestructorDecl(isDefinition()).bind(SpecialFunction),
-                       this);
-    Finder->addMatcher(
-        cxxConstructorDecl(
-            isDefinition(),
-            anyOf(
-                // Default constructor.
-                allOf(unless(hasAnyConstructorInitializer(isWritten())),
-                      parameterCountIs(0)),
-                // Copy constructor.
-                allOf(isCopyConstructor(),
-                      // Discard constructors that can be used as a copy
-                      // constructor because all the other arguments have
-                      // default values.
-                      parameterCountIs(1))))
-            .bind(SpecialFunction),
-        this);
-    // Copy-assignment operator.
-    Finder->addMatcher(
-        cxxMethodDecl(isDefinition(), isCopyAssignmentOperator(),
-                      // isCopyAssignmentOperator() allows the parameter to be
-                      // passed by value, and in this case it cannot be
-                      // defaulted.
-                      hasParameter(0, hasType(lValueReferenceType())))
-            .bind(SpecialFunction),
-        this);
-  }
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  // Destructor.
+  Finder->addMatcher(cxxDestructorDecl(isDefinition()).bind(SpecialFunction),
+                     this);
+  Finder->addMatcher(
+      cxxConstructorDecl(
+          isDefinition(),
+          anyOf(
+              // Default constructor.
+              allOf(unless(hasAnyConstructorInitializer(isWritten())),
+                    parameterCountIs(0)),
+              // Copy constructor.
+              allOf(isCopyConstructor(),
+                    // Discard constructors that can be used as a copy
+                    // constructor because all the other arguments have
+                    // default values.
+                    parameterCountIs(1))))
+          .bind(SpecialFunction),
+      this);
+  // Copy-assignment operator.
+  Finder->addMatcher(
+      cxxMethodDecl(isDefinition(), isCopyAssignmentOperator(),
+                    // isCopyAssignmentOperator() allows the parameter to be
+                    // passed by value, and in this case it cannot be
+                    // defaulted.
+                    hasParameter(0, hasType(lValueReferenceType())))
+          .bind(SpecialFunction),
+      this);
 }
 
 void UseEqualsDefaultCheck::check(const MatchFinder::MatchResult &Result) {
@@ -236,6 +246,9 @@
   const auto *SpecialFunctionDecl =
       Result.Nodes.getNodeAs<CXXMethodDecl>(SpecialFunction);
 
+  if (IgnoreMacros && SpecialFunctionDecl->getLocation().isMacroID())
+    return;
+
   // Discard explicitly deleted/defaulted special member functions and those
   // that are not user-provided (automatically generated).
   if (SpecialFunctionDecl->isDeleted() ||
diff --git a/clang-tidy/modernize/UseEqualsDefaultCheck.h b/clang-tidy/modernize/UseEqualsDefaultCheck.h
index dfefed6..a55c222 100644
--- a/clang-tidy/modernize/UseEqualsDefaultCheck.h
+++ b/clang-tidy/modernize/UseEqualsDefaultCheck.h
@@ -37,10 +37,13 @@
 /// http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-equals-default.html
 class UseEqualsDefaultCheck : public ClangTidyCheck {
 public:
-  UseEqualsDefaultCheck(StringRef Name, ClangTidyContext *Context)
-      : ClangTidyCheck(Name, Context) {}
+  UseEqualsDefaultCheck(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 IgnoreMacros;
 };
 
 } // namespace modernize
diff --git a/clang-tidy/modernize/UseNullptrCheck.cpp b/clang-tidy/modernize/UseNullptrCheck.cpp
index 198ccb0..9c7eb04 100644
--- a/clang-tidy/modernize/UseNullptrCheck.cpp
+++ b/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -200,12 +200,14 @@
       return true;
     }
 
-    if (!FirstSubExpr)
-      FirstSubExpr = C->getSubExpr()->IgnoreParens();
-
-    // Ignore the expr if it is already a nullptr literal expr.
-    if (isa<CXXNullPtrLiteralExpr>(FirstSubExpr))
+    auto* CastSubExpr = C->getSubExpr()->IgnoreParens();
+    // Ignore cast expressions which cast nullptr literal.
+    if (isa<CXXNullPtrLiteralExpr>(CastSubExpr)) {
       return true;
+    }
+
+    if (!FirstSubExpr)
+      FirstSubExpr = CastSubExpr;
 
     if (C->getCastKind() != CK_NullToPointer &&
         C->getCastKind() != CK_NullToMemberPointer) {
@@ -233,7 +235,7 @@
           allArgUsesValid(C)) {
         replaceWithNullptr(Check, SM, FileLocStart, FileLocEnd);
       }
-      return skipSubTree();
+      return true;
     }
 
     if (SM.isMacroBodyExpansion(StartLoc) && SM.isMacroBodyExpansion(EndLoc)) {
diff --git a/clang-tidy/modernize/UseOverrideCheck.cpp b/clang-tidy/modernize/UseOverrideCheck.cpp
index f6202c7..9429eb2 100644
--- a/clang-tidy/modernize/UseOverrideCheck.cpp
+++ b/clang-tidy/modernize/UseOverrideCheck.cpp
@@ -38,11 +38,16 @@
                  File.end());
   SmallVector<Token, 16> Tokens;
   Token Tok;
+  int NestedParens = 0;
   while (!RawLexer.LexFromRawLexer(Tok)) {
-    if (Tok.is(tok::semi) || Tok.is(tok::l_brace))
+    if ((Tok.is(tok::semi) || Tok.is(tok::l_brace)) && NestedParens == 0)
       break;
     if (Sources.isBeforeInTranslationUnit(Range.getEnd(), Tok.getLocation()))
       break;
+    if (Tok.is(tok::l_paren))
+      ++NestedParens;
+    else if (Tok.is(tok::r_paren))
+      --NestedParens;
     if (Tok.is(tok::raw_identifier)) {
       IdentifierInfo &Info = Result.Context->Idents.get(StringRef(
           Sources.getCharacterData(Tok.getLocation()), Tok.getLength()));
diff --git a/clang-tidy/performance/CMakeLists.txt b/clang-tidy/performance/CMakeLists.txt
index 102e76e..4b5541f 100644
--- a/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tidy/performance/CMakeLists.txt
@@ -3,7 +3,7 @@
 add_clang_library(clangTidyPerformanceModule
   FasterStringFindCheck.cpp
   ForRangeCopyCheck.cpp
-  ImplicitCastInLoopCheck.cpp
+  ImplicitConversionInLoopCheck.cpp
   InefficientStringConcatenationCheck.cpp
   InefficientVectorOperationCheck.cpp
   PerformanceTidyModule.cpp
diff --git a/clang-tidy/performance/FasterStringFindCheck.cpp b/clang-tidy/performance/FasterStringFindCheck.cpp
index 29dac1b..eddc52b 100644
--- a/clang-tidy/performance/FasterStringFindCheck.cpp
+++ b/clang-tidy/performance/FasterStringFindCheck.cpp
@@ -74,9 +74,11 @@
           callee(functionDecl(StringFindFunctions).bind("func")),
           anyOf(argumentCountIs(1), argumentCountIs(2)),
           hasArgument(0, SingleChar),
-          on(expr(hasType(recordDecl(hasAnyName(SmallVector<StringRef, 4>(
-                      StringLikeClasses.begin(), StringLikeClasses.end())))),
-                  unless(hasSubstitutedType())))),
+          on(expr(
+              hasType(hasUnqualifiedDesugaredType(recordType(hasDeclaration(
+                  recordDecl(hasAnyName(SmallVector<StringRef, 4>(
+                      StringLikeClasses.begin(), StringLikeClasses.end()))))))),
+              unless(hasSubstitutedType())))),
       this);
 }
 
diff --git a/clang-tidy/performance/ImplicitCastInLoopCheck.cpp b/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp
similarity index 73%
rename from clang-tidy/performance/ImplicitCastInLoopCheck.cpp
rename to clang-tidy/performance/ImplicitConversionInLoopCheck.cpp
index 7bd3f8a..2acbca3 100644
--- a/clang-tidy/performance/ImplicitCastInLoopCheck.cpp
+++ b/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp
@@ -1,4 +1,4 @@
-//===--- ImplicitCastInLoopCheck.cpp - clang-tidy--------------------------===//
+//===--- ImplicitConversionInLoopCheck.cpp - clang-tidy--------------------===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -7,7 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "ImplicitCastInLoopCheck.h"
+#include "ImplicitConversionInLoopCheck.h"
 
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
@@ -21,30 +21,30 @@
 namespace tidy {
 namespace performance {
 
-namespace {
 // Checks if the stmt is a ImplicitCastExpr with a CastKind that is not a NoOp.
 // The subtelty is that in some cases (user defined conversions), we can
 // get to ImplicitCastExpr inside each other, with the outer one a NoOp. In this
 // case we skip the first cast expr.
-bool IsNonTrivialImplicitCast(const Stmt *ST) {
+static bool IsNonTrivialImplicitCast(const Stmt *ST) {
   if (const auto *ICE = dyn_cast<ImplicitCastExpr>(ST)) {
     return (ICE->getCastKind() != CK_NoOp) ||
            IsNonTrivialImplicitCast(ICE->getSubExpr());
   }
   return false;
 }
-} // namespace
 
-void ImplicitCastInLoopCheck::registerMatchers(MatchFinder *Finder) {
+void ImplicitConversionInLoopCheck::registerMatchers(MatchFinder *Finder) {
   // We look for const ref loop variables that (optionally inside an
-  // ExprWithCleanup) materialize a temporary, and contain a implicit cast. The
-  // check on the implicit cast is done in check() because we can't access
-  // implicit cast subnode via matchers: has() skips casts and materialize!
-  // We also bind on the call to operator* to get the proper type in the
-  // diagnostic message.
-  // Note that when the implicit cast is done through a user defined cast
-  // operator, the node is a CXXMemberCallExpr, not a CXXOperatorCallExpr, so
-  // it should not get caught by the cxxOperatorCallExpr() matcher.
+  // ExprWithCleanup) materialize a temporary, and contain a implicit
+  // conversion. The check on the implicit conversion is done in check() because
+  // we can't access implicit conversion subnode via matchers: has() skips casts
+  // and materialize! We also bind on the call to operator* to get the proper
+  // type in the diagnostic message.
+  //
+  // Note that when the implicit conversion is done through a user defined
+  // conversion operator, the node is a CXXMemberCallExpr, not a
+  // CXXOperatorCallExpr, so it should not get caught by the
+  // cxxOperatorCallExpr() matcher.
   Finder->addMatcher(
       cxxForRangeStmt(hasLoopVariable(
           varDecl(hasType(qualType(references(qualType(isConstQualified())))),
@@ -55,7 +55,8 @@
       this);
 }
 
-void ImplicitCastInLoopCheck::check(const MatchFinder::MatchResult &Result) {
+void ImplicitConversionInLoopCheck::check(
+    const MatchFinder::MatchResult &Result) {
   const auto *VD = Result.Nodes.getNodeAs<VarDecl>("faulty-var");
   const auto *Init = Result.Nodes.getNodeAs<Expr>("init");
   const auto *OperatorCall =
@@ -76,7 +77,7 @@
     ReportAndFix(Result.Context, VD, OperatorCall);
 }
 
-void ImplicitCastInLoopCheck::ReportAndFix(
+void ImplicitConversionInLoopCheck::ReportAndFix(
     const ASTContext *Context, const VarDecl *VD,
     const CXXOperatorCallExpr *OperatorCall) {
   // We only match on const ref, so we should print a const ref version of the
@@ -85,8 +86,8 @@
   QualType ConstRefType = Context->getLValueReferenceType(ConstType);
   const char Message[] =
       "the type of the loop variable %0 is different from the one returned "
-      "by the iterator and generates an implicit cast; you can either "
-      "change the type to the correct one (%1 but 'const auto&' is always a "
+      "by the iterator and generates an implicit conversion; you can either "
+      "change the type to the matching one (%1 but 'const auto&' is always a "
       "valid option) or remove the reference to make it explicit that you are "
       "creating a new value";
   diag(VD->getLocStart(), Message) << VD << ConstRefType;
diff --git a/clang-tidy/performance/ImplicitCastInLoopCheck.h b/clang-tidy/performance/ImplicitConversionInLoopCheck.h
similarity index 80%
rename from clang-tidy/performance/ImplicitCastInLoopCheck.h
rename to clang-tidy/performance/ImplicitConversionInLoopCheck.h
index 3a9659d..8a459ab 100644
--- a/clang-tidy/performance/ImplicitCastInLoopCheck.h
+++ b/clang-tidy/performance/ImplicitConversionInLoopCheck.h
@@ -1,4 +1,4 @@
-//===--- ImplicitCastInLoopCheck.h - clang-tidy------------------*- C++ -*-===//
+//===--- ImplicitConversionInLoopCheck.h - clang-tidy------------*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -7,8 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_IMPLICIT_CAST_IN_LOOP_CHECK_H_
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_IMPLICIT_CAST_IN_LOOP_CHECK_H_
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_IMPLICIT_CONVERSION_IN_LOOP_CHECK_H_
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_IMPLICIT_CONVERSION_IN_LOOP_CHECK_H_
 
 #include "../ClangTidy.h"
 
@@ -19,9 +19,9 @@
 // Checks that in a for range loop, if the provided type is a reference, then
 // the underlying type is the one returned by the iterator (i.e. that there
 // isn't any implicit conversion).
-class ImplicitCastInLoopCheck : public ClangTidyCheck {
+class ImplicitConversionInLoopCheck : public ClangTidyCheck {
 public:
-  ImplicitCastInLoopCheck(StringRef Name, ClangTidyContext *Context)
+  ImplicitConversionInLoopCheck(StringRef Name, ClangTidyContext *Context)
       : ClangTidyCheck(Name, Context) {}
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
@@ -35,4 +35,4 @@
 } // namespace tidy
 } // namespace clang
 
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_IMPLICIT_CAST_IN_LOOP_CHECK_H_
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_IMPLICIT_CONVERSION_IN_LOOP_CHECK_H_
diff --git a/clang-tidy/performance/InefficientStringConcatenationCheck.cpp b/clang-tidy/performance/InefficientStringConcatenationCheck.cpp
index fb53167..a17916d 100644
--- a/clang-tidy/performance/InefficientStringConcatenationCheck.cpp
+++ b/clang-tidy/performance/InefficientStringConcatenationCheck.cpp
@@ -33,7 +33,8 @@
     return;
 
   const auto BasicStringType =
-      hasType(cxxRecordDecl(hasName("::std::basic_string")));
+      hasType(qualType(hasUnqualifiedDesugaredType(recordType(
+          hasDeclaration(cxxRecordDecl(hasName("::std::basic_string")))))));
 
   const auto BasicStringPlusOperator = cxxOperatorCallExpr(
       hasOverloadedOperatorName("+"),
diff --git a/clang-tidy/performance/PerformanceTidyModule.cpp b/clang-tidy/performance/PerformanceTidyModule.cpp
index 072f817..b465250 100644
--- a/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -12,7 +12,7 @@
 #include "../ClangTidyModuleRegistry.h"
 #include "FasterStringFindCheck.h"
 #include "ForRangeCopyCheck.h"
-#include "ImplicitCastInLoopCheck.h"
+#include "ImplicitConversionInLoopCheck.h"
 #include "InefficientStringConcatenationCheck.h"
 #include "InefficientVectorOperationCheck.h"
 #include "TypePromotionInMathFnCheck.h"
@@ -30,8 +30,8 @@
         "performance-faster-string-find");
     CheckFactories.registerCheck<ForRangeCopyCheck>(
         "performance-for-range-copy");
-    CheckFactories.registerCheck<ImplicitCastInLoopCheck>(
-        "performance-implicit-cast-in-loop");
+    CheckFactories.registerCheck<ImplicitConversionInLoopCheck>(
+        "performance-implicit-conversion-in-loop");
     CheckFactories.registerCheck<InefficientStringConcatenationCheck>(
         "performance-inefficient-string-concatenation");
     CheckFactories.registerCheck<InefficientVectorOperationCheck>(
diff --git a/clang-tidy/performance/TypePromotionInMathFnCheck.cpp b/clang-tidy/performance/TypePromotionInMathFnCheck.cpp
index 82f9535..441bad3 100644
--- a/clang-tidy/performance/TypePromotionInMathFnCheck.cpp
+++ b/clang-tidy/performance/TypePromotionInMathFnCheck.cpp
@@ -33,7 +33,7 @@
     StringRef Name, ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
       IncludeStyle(utils::IncludeSorter::parseIncludeStyle(
-          Options.get("IncludeStyle", "llvm"))) {}
+          Options.getLocalOrGlobal("IncludeStyle", "llvm"))) {}
 
 void TypePromotionInMathFnCheck::registerPPCallbacks(
     CompilerInstance &Compiler) {
diff --git a/clang-tidy/performance/UnnecessaryValueParamCheck.cpp b/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
index a34f707..0dc47d5 100644
--- a/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
+++ b/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
@@ -58,13 +58,25 @@
   return Matches.empty();
 }
 
+bool isExplicitTemplateSpecialization(const FunctionDecl &Function) {
+  if (const auto *SpecializationInfo = Function.getTemplateSpecializationInfo())
+    if (SpecializationInfo->getTemplateSpecializationKind() ==
+        TSK_ExplicitSpecialization)
+      return true;
+  if (const auto *Method = llvm::dyn_cast<CXXMethodDecl>(&Function))
+    if (Method->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization &&
+        Method->getMemberSpecializationInfo()->isExplicitSpecialization())
+      return true;
+  return false;
+}
+
 } // namespace
 
 UnnecessaryValueParamCheck::UnnecessaryValueParamCheck(
     StringRef Name, ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
       IncludeStyle(utils::IncludeSorter::parseIncludeStyle(
-          Options.get("IncludeStyle", "llvm"))) {}
+          Options.getLocalOrGlobal("IncludeStyle", "llvm"))) {}
 
 void UnnecessaryValueParamCheck::registerMatchers(MatchFinder *Finder) {
   const auto ExpensiveValueParamDecl =
@@ -133,9 +145,11 @@
   // 2. the function is virtual as it might break overrides
   // 3. the function is referenced outside of a call expression within the
   //    compilation unit as the signature change could introduce build errors.
+  // 4. the function is an explicit template specialization.
   const auto *Method = llvm::dyn_cast<CXXMethodDecl>(Function);
   if (Param->getLocStart().isMacroID() || (Method && Method->isVirtual()) ||
-      isReferencedOutsideOfCallExpr(*Function, *Result.Context))
+      isReferencedOutsideOfCallExpr(*Function, *Result.Context) ||
+      isExplicitTemplateSpecialization(*Function))
     return;
   for (const auto *FunctionDecl = Function; FunctionDecl != nullptr;
        FunctionDecl = FunctionDecl->getPreviousDecl()) {
diff --git a/clang-tidy/plugin/CMakeLists.txt b/clang-tidy/plugin/CMakeLists.txt
index 5106d3f..5c88832 100644
--- a/clang-tidy/plugin/CMakeLists.txt
+++ b/clang-tidy/plugin/CMakeLists.txt
@@ -8,6 +8,7 @@
   clangFrontend
   clangSema
   clangTidy
+  clangTidyAndroidModule
   clangTidyBoostModule
   clangTidyCERTModule
   clangTidyCppCoreGuidelinesModule
diff --git a/clang-tidy/readability/CMakeLists.txt b/clang-tidy/readability/CMakeLists.txt
index bed7287..a130c9b 100644
--- a/clang-tidy/readability/CMakeLists.txt
+++ b/clang-tidy/readability/CMakeLists.txt
@@ -9,7 +9,7 @@
   ElseAfterReturnCheck.cpp
   FunctionSizeCheck.cpp
   IdentifierNamingCheck.cpp
-  ImplicitBoolCastCheck.cpp
+  ImplicitBoolConversionCheck.cpp
   InconsistentDeclarationParameterNameCheck.cpp
   MisleadingIndentationCheck.cpp
   MisplacedArrayIndexCheck.cpp
@@ -25,6 +25,7 @@
   RedundantSmartptrGetCheck.cpp
   RedundantStringInitCheck.cpp
   SimplifyBooleanExprCheck.cpp
+  StaticAccessedThroughInstanceCheck.cpp
   StaticDefinitionInAnonymousNamespaceCheck.cpp
   UniqueptrDeleteReleaseCheck.cpp
 
diff --git a/clang-tidy/readability/ContainerSizeEmptyCheck.cpp b/clang-tidy/readability/ContainerSizeEmptyCheck.cpp
index 24680eb..5604354 100644
--- a/clang-tidy/readability/ContainerSizeEmptyCheck.cpp
+++ b/clang-tidy/readability/ContainerSizeEmptyCheck.cpp
@@ -32,16 +32,18 @@
   if (!getLangOpts().CPlusPlus)
     return;
 
-  const auto ValidContainer = cxxRecordDecl(isSameOrDerivedFrom(
-      namedDecl(
-          has(cxxMethodDecl(
-                  isConst(), parameterCountIs(0), isPublic(), hasName("size"),
-                  returns(qualType(isInteger(), unless(booleanType()))))
-                  .bind("size")),
-          has(cxxMethodDecl(isConst(), parameterCountIs(0), isPublic(),
-                            hasName("empty"), returns(booleanType()))
-                  .bind("empty")))
-          .bind("container")));
+  const auto ValidContainer = qualType(hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(cxxRecordDecl(isSameOrDerivedFrom(
+          namedDecl(
+              has(cxxMethodDecl(
+                      isConst(), parameterCountIs(0), isPublic(),
+                      hasName("size"),
+                      returns(qualType(isInteger(), unless(booleanType()))))
+                      .bind("size")),
+              has(cxxMethodDecl(isConst(), parameterCountIs(0), isPublic(),
+                                hasName("empty"), returns(booleanType()))
+                      .bind("empty")))
+              .bind("container")))))));
 
   const auto WrongUse = anyOf(
       hasParent(binaryOperator(
diff --git a/clang-tidy/readability/FunctionSizeCheck.cpp b/clang-tidy/readability/FunctionSizeCheck.cpp
index ea5f750..e6410ce 100644
--- a/clang-tidy/readability/FunctionSizeCheck.cpp
+++ b/clang-tidy/readability/FunctionSizeCheck.cpp
@@ -16,6 +16,7 @@
 namespace clang {
 namespace tidy {
 namespace readability {
+namespace {
 
 class FunctionASTVisitor : public RecursiveASTVisitor<FunctionASTVisitor> {
   using Base = RecursiveASTVisitor<FunctionASTVisitor>;
@@ -85,6 +86,8 @@
   unsigned CurrentNestingLevel = 0;
 };
 
+} // namespace
+
 FunctionSizeCheck::FunctionSizeCheck(StringRef Name, ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
       LineThreshold(Options.get("LineThreshold", -1U)),
diff --git a/clang-tidy/readability/ImplicitBoolCastCheck.cpp b/clang-tidy/readability/ImplicitBoolConversionCheck.cpp
similarity index 88%
rename from clang-tidy/readability/ImplicitBoolCastCheck.cpp
rename to clang-tidy/readability/ImplicitBoolConversionCheck.cpp
index 996219c..79022d4 100644
--- a/clang-tidy/readability/ImplicitBoolCastCheck.cpp
+++ b/clang-tidy/readability/ImplicitBoolConversionCheck.cpp
@@ -1,4 +1,4 @@
-//===--- ImplicitBoolCastCheck.cpp - clang-tidy----------------------------===//
+//===--- ImplicitBoolConversionCheck.cpp - clang-tidy----------------------===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -7,7 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "ImplicitBoolCastCheck.h"
+#include "ImplicitBoolConversionCheck.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/Lex/Lexer.h"
@@ -218,7 +218,7 @@
   return BoolLiteral->getValue() ? "1" : "0";
 }
 
-bool isAllowedConditionalCast(const ImplicitCastExpr *Cast,
+bool isCastAllowedInCondition(const ImplicitCastExpr *Cast,
                               ASTContext &Context) {
   std::queue<const Stmt *> Q;
   Q.push(Cast);
@@ -245,22 +245,19 @@
 
 } // anonymous namespace
 
-ImplicitBoolCastCheck::ImplicitBoolCastCheck(StringRef Name,
-                                             ClangTidyContext *Context)
+ImplicitBoolConversionCheck::ImplicitBoolConversionCheck(
+    StringRef Name, ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
-      AllowConditionalIntegerCasts(
-          Options.get("AllowConditionalIntegerCasts", false)),
-      AllowConditionalPointerCasts(
-          Options.get("AllowConditionalPointerCasts", false)) {}
+      AllowIntegerConditions(Options.get("AllowIntegerConditions", false)),
+      AllowPointerConditions(Options.get("AllowPointerConditions", false)) {}
 
-void ImplicitBoolCastCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
-  Options.store(Opts, "AllowConditionalIntegerCasts",
-                AllowConditionalIntegerCasts);
-  Options.store(Opts, "AllowConditionalPointerCasts",
-                AllowConditionalPointerCasts);
+void ImplicitBoolConversionCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "AllowIntegerConditions", AllowIntegerConditions);
+  Options.store(Opts, "AllowPointerConditions", AllowPointerConditions);
 }
 
-void ImplicitBoolCastCheck::registerMatchers(MatchFinder *Finder) {
+void ImplicitBoolConversionCheck::registerMatchers(MatchFinder *Finder) {
   // This check doesn't make much sense if we run it on language without
   // built-in bool support.
   if (!getLangOpts().Bool) {
@@ -326,7 +323,8 @@
       this);
 }
 
-void ImplicitBoolCastCheck::check(const MatchFinder::MatchResult &Result) {
+void ImplicitBoolConversionCheck::check(
+    const MatchFinder::MatchResult &Result) {
   if (const auto *CastToBool =
           Result.Nodes.getNodeAs<ImplicitCastExpr>("implicitCastToBool")) {
     const auto *Parent = Result.Nodes.getNodeAs<Stmt>("parentStmt");
@@ -341,23 +339,22 @@
   }
 }
 
-void ImplicitBoolCastCheck::handleCastToBool(const ImplicitCastExpr *Cast,
-                                             const Stmt *Parent,
-                                             ASTContext &Context) {
-  if (AllowConditionalPointerCasts &&
+void ImplicitBoolConversionCheck::handleCastToBool(const ImplicitCastExpr *Cast,
+                                                   const Stmt *Parent,
+                                                   ASTContext &Context) {
+  if (AllowPointerConditions &&
       (Cast->getCastKind() == CK_PointerToBoolean ||
        Cast->getCastKind() == CK_MemberPointerToBoolean) &&
-      isAllowedConditionalCast(Cast, Context)) {
+      isCastAllowedInCondition(Cast, Context)) {
     return;
   }
 
-  if (AllowConditionalIntegerCasts &&
-      Cast->getCastKind() == CK_IntegralToBoolean &&
-      isAllowedConditionalCast(Cast, Context)) {
+  if (AllowIntegerConditions && Cast->getCastKind() == CK_IntegralToBoolean &&
+      isCastAllowedInCondition(Cast, Context)) {
     return;
   }
 
-  auto Diag = diag(Cast->getLocStart(), "implicit cast %0 -> bool")
+  auto Diag = diag(Cast->getLocStart(), "implicit conversion %0 -> bool")
               << Cast->getSubExpr()->getType();
 
   StringRef EquivalentLiteral =
@@ -369,12 +366,13 @@
   }
 }
 
-void ImplicitBoolCastCheck::handleCastFromBool(
+void ImplicitBoolConversionCheck::handleCastFromBool(
     const ImplicitCastExpr *Cast, const ImplicitCastExpr *NextImplicitCast,
     ASTContext &Context) {
   QualType DestType =
       NextImplicitCast ? NextImplicitCast->getType() : Cast->getType();
-  auto Diag = diag(Cast->getLocStart(), "implicit cast bool -> %0") << DestType;
+  auto Diag = diag(Cast->getLocStart(), "implicit conversion bool -> %0")
+              << DestType;
 
   if (const auto *BoolLiteral =
           dyn_cast<CXXBoolLiteralExpr>(Cast->getSubExpr())) {
diff --git a/clang-tidy/readability/ImplicitBoolCastCheck.h b/clang-tidy/readability/ImplicitBoolConversionCheck.h
similarity index 75%
rename from clang-tidy/readability/ImplicitBoolCastCheck.h
rename to clang-tidy/readability/ImplicitBoolConversionCheck.h
index cd8addf..bb062e0 100644
--- a/clang-tidy/readability/ImplicitBoolCastCheck.h
+++ b/clang-tidy/readability/ImplicitBoolConversionCheck.h
@@ -1,4 +1,4 @@
-//===--- ImplicitBoolCastCheck.h - clang-tidy--------------------*- C++ -*-===//
+//===--- ImplicitBoolConversionCheck.h - clang-tidy--------------*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -7,8 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IMPLICIT_BOOL_CAST_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IMPLICIT_BOOL_CAST_H
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IMPLICIT_BOOL_CONVERSION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IMPLICIT_BOOL_CONVERSION_H
 
 #include "../ClangTidy.h"
 
@@ -16,13 +16,13 @@
 namespace tidy {
 namespace readability {
 
-/// \brief Checks for use of implicit bool casts in expressions.
+/// \brief Checks for use of implicit bool conversions in expressions.
 ///
 /// For the user-facing documentation see:
-/// http://clang.llvm.org/extra/clang-tidy/checks/readability-implicit-bool-cast.html
-class ImplicitBoolCastCheck : public ClangTidyCheck {
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-implicit-bool-conversion.html
+class ImplicitBoolConversionCheck : public ClangTidyCheck {
 public:
-  ImplicitBoolCastCheck(StringRef Name, ClangTidyContext *Context);
+  ImplicitBoolConversionCheck(StringRef Name, ClangTidyContext *Context);
   void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
 
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
@@ -35,12 +35,12 @@
                           const ImplicitCastExpr *FurtherImplicitCastExpression,
                           ASTContext &Context);
 
-  bool AllowConditionalIntegerCasts;
-  bool AllowConditionalPointerCasts;
+  const bool AllowIntegerConditions;
+  const bool AllowPointerConditions;
 };
 
 } // namespace readability
 } // namespace tidy
 } // namespace clang
 
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IMPLICIT_BOOL_CAST_H
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IMPLICIT_BOOL_CONVERSION_H
diff --git a/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tidy/readability/ReadabilityTidyModule.cpp
index dacea0d..395730d 100644
--- a/clang-tidy/readability/ReadabilityTidyModule.cpp
+++ b/clang-tidy/readability/ReadabilityTidyModule.cpp
@@ -18,7 +18,7 @@
 #include "ElseAfterReturnCheck.h"
 #include "FunctionSizeCheck.h"
 #include "IdentifierNamingCheck.h"
-#include "ImplicitBoolCastCheck.h"
+#include "ImplicitBoolConversionCheck.h"
 #include "InconsistentDeclarationParameterNameCheck.h"
 #include "MisleadingIndentationCheck.h"
 #include "MisplacedArrayIndexCheck.h"
@@ -32,6 +32,7 @@
 #include "RedundantStringCStrCheck.h"
 #include "RedundantStringInitCheck.h"
 #include "SimplifyBooleanExprCheck.h"
+#include "StaticAccessedThroughInstanceCheck.h"
 #include "StaticDefinitionInAnonymousNamespaceCheck.h"
 #include "UniqueptrDeleteReleaseCheck.h"
 
@@ -58,8 +59,8 @@
         "readability-function-size");
     CheckFactories.registerCheck<IdentifierNamingCheck>(
         "readability-identifier-naming");
-    CheckFactories.registerCheck<ImplicitBoolCastCheck>(
-        "readability-implicit-bool-cast");
+    CheckFactories.registerCheck<ImplicitBoolConversionCheck>(
+        "readability-implicit-bool-conversion");
     CheckFactories.registerCheck<InconsistentDeclarationParameterNameCheck>(
         "readability-inconsistent-declaration-parameter-name");
     CheckFactories.registerCheck<MisleadingIndentationCheck>(
@@ -70,6 +71,8 @@
         "readability-redundant-function-ptr-dereference");
     CheckFactories.registerCheck<RedundantMemberInitCheck>(
         "readability-redundant-member-init");
+    CheckFactories.registerCheck<StaticAccessedThroughInstanceCheck>(
+        "readability-static-accessed-through-instance");
     CheckFactories.registerCheck<StaticDefinitionInAnonymousNamespaceCheck>(
         "readability-static-definition-in-anonymous-namespace");
     CheckFactories.registerCheck<readability::NamedParameterCheck>(
diff --git a/clang-tidy/readability/RedundantDeclarationCheck.cpp b/clang-tidy/readability/RedundantDeclarationCheck.cpp
index 29d43c7..1df3f05 100644
--- a/clang-tidy/readability/RedundantDeclarationCheck.cpp
+++ b/clang-tidy/readability/RedundantDeclarationCheck.cpp
@@ -18,11 +18,16 @@
 namespace tidy {
 namespace readability {
 
+RedundantDeclarationCheck::RedundantDeclarationCheck(StringRef Name,
+                                                     ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true)) {}
+
 void RedundantDeclarationCheck::registerMatchers(MatchFinder *Finder) {
   Finder->addMatcher(
-      namedDecl(
-          anyOf(varDecl(unless(isDefinition())),
-                functionDecl(unless(anyOf(isDefinition(), isDefaulted())))))
+      namedDecl(anyOf(varDecl(unless(isDefinition())),
+                      functionDecl(unless(anyOf(isDefinition(), isDefaulted(),
+                                                hasParent(friendDecl()))))))
           .bind("Decl"),
       this);
 }
@@ -36,6 +41,13 @@
     return;
   if (Prev->getLocation() == D->getLocation())
     return;
+  if (IgnoreMacros &&
+      (D->getLocation().isMacroID() || Prev->getLocation().isMacroID()))
+    return;
+  // Don't complain when the previous declaration is a friend declaration.
+  for (const auto &Parent : Result.Context->getParents(*Prev))
+    if (Parent.get<FriendDecl>())
+      return;
 
   const SourceManager &SM = *Result.SourceManager;
 
diff --git a/clang-tidy/readability/RedundantDeclarationCheck.h b/clang-tidy/readability/RedundantDeclarationCheck.h
index 96c4830..9be79b8 100644
--- a/clang-tidy/readability/RedundantDeclarationCheck.h
+++ b/clang-tidy/readability/RedundantDeclarationCheck.h
@@ -22,10 +22,12 @@
 /// http://clang.llvm.org/extra/clang-tidy/checks/readability-redundant-declaration.html
 class RedundantDeclarationCheck : public ClangTidyCheck {
 public:
-  RedundantDeclarationCheck(StringRef Name, ClangTidyContext *Context)
-      : ClangTidyCheck(Name, Context) {}
+  RedundantDeclarationCheck(StringRef Name, ClangTidyContext *Context);
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  const bool IgnoreMacros;
 };
 
 } // namespace readability
diff --git a/clang-tidy/readability/RedundantMemberInitCheck.cpp b/clang-tidy/readability/RedundantMemberInitCheck.cpp
index 6d36500..8409f9f 100644
--- a/clang-tidy/readability/RedundantMemberInitCheck.cpp
+++ b/clang-tidy/readability/RedundantMemberInitCheck.cpp
@@ -39,7 +39,8 @@
           forEachConstructorInitializer(
               cxxCtorInitializer(isWritten(),
                                  withInitializer(ignoringImplicit(Construct)),
-                                 unless(forField(hasType(isConstQualified()))))
+                                 unless(forField(hasType(isConstQualified()))),
+                                 unless(forField(hasParent(recordDecl(isUnion())))))
                   .bind("init"))),
       this);
 }
@@ -52,7 +53,7 @@
       Construct->getArg(0)->isDefaultArgument()) {
     if (Init->isAnyMemberInitializer()) {
       diag(Init->getSourceLocation(), "initializer for member %0 is redundant")
-          << Init->getMember()
+          << Init->getAnyMember()
           << FixItHint::CreateRemoval(Init->getSourceRange());
     } else {
       diag(Init->getSourceLocation(),
diff --git a/clang-tidy/readability/RedundantStringCStrCheck.cpp b/clang-tidy/readability/RedundantStringCStrCheck.cpp
index c6b384b..21f4a8a 100644
--- a/clang-tidy/readability/RedundantStringCStrCheck.cpp
+++ b/clang-tidy/readability/RedundantStringCStrCheck.cpp
@@ -77,7 +77,8 @@
     return;
 
   // Match expressions of type 'string' or 'string*'.
-  const auto StringDecl = cxxRecordDecl(hasName("::std::basic_string"));
+  const auto StringDecl = type(hasUnqualifiedDesugaredType(recordType(
+      hasDeclaration(cxxRecordDecl(hasName("::std::basic_string"))))));
   const auto StringExpr =
       expr(anyOf(hasType(StringDecl), hasType(qualType(pointsTo(StringDecl)))));
 
diff --git a/clang-tidy/readability/RedundantStringInitCheck.cpp b/clang-tidy/readability/RedundantStringInitCheck.cpp
index b881e22..46ce2a4 100644
--- a/clang-tidy/readability/RedundantStringInitCheck.cpp
+++ b/clang-tidy/readability/RedundantStringInitCheck.cpp
@@ -47,7 +47,8 @@
   //     string bar("");
   Finder->addMatcher(
       namedDecl(
-          varDecl(hasType(cxxRecordDecl(hasName("basic_string"))),
+          varDecl(hasType(hasUnqualifiedDesugaredType(recordType(
+                      hasDeclaration(cxxRecordDecl(hasName("basic_string")))))),
                   hasInitializer(expr(ignoringImplicit(anyOf(
                                           EmptyStringCtorExpr,
                                           EmptyStringCtorExprWithTemporaries)))
diff --git a/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp b/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
new file mode 100644
index 0000000..b136577
--- /dev/null
+++ b/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
@@ -0,0 +1,90 @@
+//===--- StaticAccessedThroughInstanceCheck.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 "StaticAccessedThroughInstanceCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+static unsigned getNameSpecifierNestingLevel(const QualType &QType) {
+  if (const ElaboratedType *ElType = QType->getAs<ElaboratedType>()) {
+    const NestedNameSpecifier *NestedSpecifiers = ElType->getQualifier();
+    unsigned NameSpecifierNestingLevel = 1;
+    do {
+      NameSpecifierNestingLevel++;
+      NestedSpecifiers = NestedSpecifiers->getPrefix();
+    } while (NestedSpecifiers);
+
+    return NameSpecifierNestingLevel;
+  }
+  return 0;
+}
+
+void StaticAccessedThroughInstanceCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "NameSpecifierNestingThreshold",
+                NameSpecifierNestingThreshold);
+}
+
+void StaticAccessedThroughInstanceCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      memberExpr(hasDeclaration(anyOf(cxxMethodDecl(isStaticStorageClass()),
+                                      varDecl(hasStaticStorageDuration()))),
+                 unless(isInTemplateInstantiation()))
+          .bind("memberExpression"),
+      this);
+}
+
+void StaticAccessedThroughInstanceCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *MemberExpression =
+      Result.Nodes.getNodeAs<MemberExpr>("memberExpression");
+
+  if (MemberExpression->getLocStart().isMacroID())
+    return;
+
+  const Expr *BaseExpr = MemberExpression->getBase();
+
+  // Do not warn for overlaoded -> operators.
+  if (isa<CXXOperatorCallExpr>(BaseExpr))
+    return;
+
+  QualType BaseType =
+      BaseExpr->getType()->isPointerType()
+          ? BaseExpr->getType()->getPointeeType().getUnqualifiedType()
+          : BaseExpr->getType().getUnqualifiedType();
+
+  const ASTContext *AstContext = Result.Context;
+  PrintingPolicy PrintingPolicyWithSupressedTag(AstContext->getLangOpts());
+  PrintingPolicyWithSupressedTag.SuppressTagKeyword = true;
+  std::string BaseTypeName =
+      BaseType.getAsString(PrintingPolicyWithSupressedTag);
+
+  SourceLocation MemberExprStartLoc = MemberExpression->getLocStart();
+  auto Diag =
+      diag(MemberExprStartLoc, "static member accessed through instance");
+
+  if (BaseExpr->HasSideEffects(*AstContext) ||
+      getNameSpecifierNestingLevel(BaseType) > NameSpecifierNestingThreshold)
+    return;
+
+  Diag << FixItHint::CreateReplacement(
+      CharSourceRange::getCharRange(MemberExprStartLoc,
+                                    MemberExpression->getMemberLoc()),
+      BaseTypeName + "::");
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/readability/StaticAccessedThroughInstanceCheck.h b/clang-tidy/readability/StaticAccessedThroughInstanceCheck.h
new file mode 100644
index 0000000..c2eebab
--- /dev/null
+++ b/clang-tidy/readability/StaticAccessedThroughInstanceCheck.h
@@ -0,0 +1,43 @@
+//===--- StaticAccessedThroughInstanceCheck.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_READABILITY_STATIC_ACCESSED_THROUGH_INSTANCE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_STATIC_ACCESSED_THROUGH_INSTANCE_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// \@brief Checks for member expressions that access static members through
+/// instances and replaces them with uses of the appropriate qualified-id.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-static-accessed-through-instance.html
+class StaticAccessedThroughInstanceCheck : public ClangTidyCheck {
+public:
+  StaticAccessedThroughInstanceCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context),
+        NameSpecifierNestingThreshold(
+            Options.get("NameSpecifierNestingThreshold", 3)) {}
+
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  const unsigned NameSpecifierNestingThreshold;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_STATIC_ACCESSED_THROUGH_INSTANCE_H
diff --git a/clang-tidy/tool/CMakeLists.txt b/clang-tidy/tool/CMakeLists.txt
index 55d352a..b8c34f3 100644
--- a/clang-tidy/tool/CMakeLists.txt
+++ b/clang-tidy/tool/CMakeLists.txt
@@ -13,7 +13,9 @@
   clangASTMatchers
   clangBasic
   clangTidy
+  clangTidyAndroidModule
   clangTidyBoostModule
+  clangTidyBugproneModule
   clangTidyCERTModule
   clangTidyCppCoreGuidelinesModule
   clangTidyGoogleModule
diff --git a/clang-tidy/tool/ClangTidyMain.cpp b/clang-tidy/tool/ClangTidyMain.cpp
index 04baa7b..a57fde8 100644
--- a/clang-tidy/tool/ClangTidyMain.cpp
+++ b/clang-tidy/tool/ClangTidyMain.cpp
@@ -392,13 +392,13 @@
   if (EnabledChecks.empty()) {
     llvm::errs() << "Error: no checks enabled.\n";
     llvm::cl::PrintHelpMessage(/*Hidden=*/false, /*Categorized=*/true);
-    return 1;
+    return 0;
   }
 
   if (PathList.empty()) {
     llvm::errs() << "Error: no input files specified.\n";
     llvm::cl::PrintHelpMessage(/*Hidden=*/false, /*Categorized=*/true);
-    return 1;
+    return 0;
   }
 
   ProfileData Profile;
@@ -462,6 +462,11 @@
 static int LLVM_ATTRIBUTE_UNUSED BoostModuleAnchorDestination =
     BoostModuleAnchorSource;
 
+// This anchor is used to force the linker to link the BugproneModule.
+extern volatile int BugproneModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED BugproneModuleAnchorDestination =
+    BugproneModuleAnchorSource;
+
 // This anchor is used to force the linker to link the LLVMModule.
 extern volatile int LLVMModuleAnchorSource;
 static int LLVM_ATTRIBUTE_UNUSED LLVMModuleAnchorDestination =
@@ -477,6 +482,11 @@
 static int LLVM_ATTRIBUTE_UNUSED GoogleModuleAnchorDestination =
     GoogleModuleAnchorSource;
 
+// This anchor is used to force the linker to link the AndroidModule.
+extern volatile int AndroidModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED AndroidModuleAnchorDestination =
+    AndroidModuleAnchorSource;
+
 // This anchor is used to force the linker to link the MiscModule.
 extern volatile int MiscModuleAnchorSource;
 static int LLVM_ATTRIBUTE_UNUSED MiscModuleAnchorDestination =
diff --git a/clang-tidy/tool/run-clang-tidy.py b/clang-tidy/tool/run-clang-tidy.py
index d9d827b..7792c5a 100755
--- a/clang-tidy/tool/run-clang-tidy.py
+++ b/clang-tidy/tool/run-clang-tidy.py
@@ -35,11 +35,12 @@
 """
 
 from __future__ import print_function
+
 import argparse
+import glob
 import json
 import multiprocessing
 import os
-import Queue
 import re
 import shutil
 import subprocess
@@ -47,7 +48,14 @@
 import tempfile
 import threading
 import traceback
+import yaml
 
+is_py2 = sys.version[0] == '2'
+
+if is_py2:
+    import Queue as queue
+else:
+    import queue as queue
 
 def find_compilation_database(path):
   """Adjusts the directory until a compilation database is found."""
@@ -89,6 +97,31 @@
   return start
 
 
+def merge_replacement_files(tmpdir, mergefile):
+  """Merge all replacement files in a directory into a single file"""
+  # The fixes suggested by clang-tidy >= 4.0.0 are given under
+  # the top level key 'Diagnostics' in the output yaml files
+  mergekey="Diagnostics"
+  merged=[]
+  for replacefile in glob.iglob(os.path.join(tmpdir, '*.yaml')):
+    content = yaml.safe_load(open(replacefile, 'r'))
+    if not content:
+      continue # Skip empty files.
+    merged.extend(content.get(mergekey, []))
+
+  if merged:
+    # MainSourceFile: The key is required by the definition inside
+    # include/clang/Tooling/ReplacementsYaml.h, but the value
+    # is actually never used inside clang-apply-replacements,
+    # so we set it to '' here.
+    output = { 'MainSourceFile': '', mergekey: merged }
+    with open(mergefile, 'w') as out:
+      yaml.safe_dump(output, out)
+  else:
+    # Empty the file:
+    open(mergefile, 'w').close()
+
+
 def check_clang_apply_replacements_binary(args):
   """Checks if invoking supplied clang-apply-replacements binary works."""
   try:
@@ -101,7 +134,7 @@
 
 
 def apply_fixes(args, tmpdir):
-  """Calls clang-apply-fixes on a given directory. Deletes the dir when done."""
+  """Calls clang-apply-fixes on a given directory."""
   invocation = [args.clang_apply_replacements_binary]
   if args.format:
     invocation.append('-format')
@@ -143,6 +176,9 @@
                       'headers to output diagnostics from. Diagnostics from '
                       'the main file of each translation unit are always '
                       'displayed.')
+  parser.add_argument('-export-fixes', metavar='filename', dest='export_fixes',
+                      help='Create a yaml file to store suggested fixes in, '
+                      'which can be applied with clang-apply-replacements.')
   parser.add_argument('-j', type=int, default=0,
                       help='number of tidy instances to be run in parallel.')
   parser.add_argument('files', nargs='*', default=['.*'],
@@ -194,7 +230,7 @@
     max_task = multiprocessing.cpu_count()
 
   tmpdir = None
-  if args.fix:
+  if args.fix or args.export_fixes:
     check_clang_apply_replacements_binary(args)
     tmpdir = tempfile.mkdtemp()
 
@@ -203,43 +239,51 @@
 
   try:
     # Spin up a bunch of tidy-launching threads.
-    queue = Queue.Queue(max_task)
+    task_queue = queue.Queue(max_task)
     for _ in range(max_task):
       t = threading.Thread(target=run_tidy,
-                           args=(args, tmpdir, build_path, queue))
+                           args=(args, tmpdir, build_path, task_queue))
       t.daemon = True
       t.start()
 
     # Fill the queue with files.
     for name in files:
       if file_name_re.search(name):
-        queue.put(name)
+        task_queue.put(name)
 
     # Wait for all threads to be done.
-    queue.join()
+    task_queue.join()
 
   except KeyboardInterrupt:
     # This is a sad hack. Unfortunately subprocess goes
     # bonkers with ctrl-c and we start forking merrily.
     print('\nCtrl-C detected, goodbye.')
-    if args.fix:
+    if tmpdir:
       shutil.rmtree(tmpdir)
     os.kill(0, 9)
 
+  return_code = 0
+  if args.export_fixes:
+    print('Writing fixes to ' + args.export_fixes + ' ...')
+    try:
+      merge_replacement_files(tmpdir, args.export_fixes)
+    except:
+      print('Error exporting fixes.\n', file=sys.stderr)
+      traceback.print_exc()
+      return_code=1
+
   if args.fix:
     print('Applying fixes ...')
-    successfully_applied = False
-
     try:
       apply_fixes(args, tmpdir)
-      successfully_applied = True
     except:
       print('Error applying fixes.\n', file=sys.stderr)
       traceback.print_exc()
+      return_code=1
 
+  if tmpdir:
     shutil.rmtree(tmpdir)
-    if not successfully_applied:
-      sys.exit(1)
+  sys.exit(return_code)
 
 if __name__ == '__main__':
   main()
diff --git a/clang-tidy/utils/ASTUtils.cpp b/clang-tidy/utils/ASTUtils.cpp
index eff45b5..1efcec9 100644
--- a/clang-tidy/utils/ASTUtils.cpp
+++ b/clang-tidy/utils/ASTUtils.cpp
@@ -11,6 +11,7 @@
 
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Lex/Lexer.h"
 
 namespace clang {
 namespace tidy {
@@ -39,6 +40,33 @@
   return false;
 }
 
+bool exprHasBitFlagWithSpelling(const Expr *Flags, const SourceManager &SM,
+                                const LangOptions &LangOpts,
+                                StringRef FlagName) {
+  // If the Flag is an integer constant, check it.
+  if (isa<IntegerLiteral>(Flags)) {
+    if (!SM.isMacroBodyExpansion(Flags->getLocStart()) &&
+        !SM.isMacroArgExpansion(Flags->getLocStart()))
+      return false;
+
+    // Get the marco name.
+    auto MacroName = Lexer::getSourceText(
+        CharSourceRange::getTokenRange(Flags->getSourceRange()), SM, LangOpts);
+
+    return MacroName == FlagName;
+  }
+  // If it's a binary OR operation.
+  if (const auto *BO = dyn_cast<BinaryOperator>(Flags))
+    if (BO->getOpcode() == clang::BinaryOperatorKind::BO_Or)
+      return exprHasBitFlagWithSpelling(BO->getLHS()->IgnoreParenCasts(), SM,
+                                        LangOpts, FlagName) ||
+             exprHasBitFlagWithSpelling(BO->getRHS()->IgnoreParenCasts(), SM,
+                                        LangOpts, FlagName);
+
+  // Otherwise, assume it has the flag.
+  return true;
+}
+
 } // namespace utils
 } // namespace tidy
 } // namespace clang
diff --git a/clang-tidy/utils/ASTUtils.h b/clang-tidy/utils/ASTUtils.h
index 7f75327..ccff000 100644
--- a/clang-tidy/utils/ASTUtils.h
+++ b/clang-tidy/utils/ASTUtils.h
@@ -20,6 +20,13 @@
                                            const Stmt &Statement);
 // Determine whether Expr is a Binary or Ternary expression.
 bool IsBinaryOrTernary(const Expr *E);
+
+/// Checks whether a macro flag is present in the given argument. Only considers
+/// cases of single match or match in a binary OR expression. For example,
+/// <needed-flag> or <flag> | <needed-flag> | ...
+bool exprHasBitFlagWithSpelling(const Expr *Flags, const SourceManager &SM,
+                                const LangOptions &LangOpts,
+                                StringRef FlagName);
 } // namespace utils
 } // namespace tidy
 } // namespace clang
diff --git a/clang-tidy/utils/HeaderFileExtensionsUtils.h b/clang-tidy/utils/HeaderFileExtensionsUtils.h
index c9fedf0..2012017 100644
--- a/clang-tidy/utils/HeaderFileExtensionsUtils.h
+++ b/clang-tidy/utils/HeaderFileExtensionsUtils.h
@@ -36,6 +36,10 @@
     SourceLocation Loc, SourceManager &SM,
     const HeaderFileExtensionsSet &HeaderFileExtensions);
 
+/// \brief Returns recommended default value for the list of header file
+/// extensions.
+inline StringRef defaultHeaderFileExtensions() { return ",h,hh,hpp,hxx"; }
+
 /// \brief Parses header file extensions from a semicolon-separated list.
 bool parseHeaderFileExtensions(StringRef AllHeaderFileExtensions,
                                HeaderFileExtensionsSet &HeaderFileExtensions,
diff --git a/clang-tidy/utils/HeaderGuard.h b/clang-tidy/utils/HeaderGuard.h
index c90a312..a2d8288 100644
--- a/clang-tidy/utils/HeaderGuard.h
+++ b/clang-tidy/utils/HeaderGuard.h
@@ -28,8 +28,8 @@
 public:
   HeaderGuardCheck(StringRef Name, ClangTidyContext *Context)
       : ClangTidyCheck(Name, Context),
-        RawStringHeaderFileExtensions(
-            Options.getLocalOrGlobal("HeaderFileExtensions", ",h,hh,hpp,hxx")) {
+        RawStringHeaderFileExtensions(Options.getLocalOrGlobal(
+            "HeaderFileExtensions", utils::defaultHeaderFileExtensions())) {
     utils::parseHeaderFileExtensions(RawStringHeaderFileExtensions,
                                      HeaderFileExtensions, ',');
   }
diff --git a/clang-tidy/utils/Matchers.h b/clang-tidy/utils/Matchers.h
index adafdd9..aeb639f 100644
--- a/clang-tidy/utils/Matchers.h
+++ b/clang-tidy/utils/Matchers.h
@@ -17,6 +17,10 @@
 namespace tidy {
 namespace matchers {
 
+AST_MATCHER(BinaryOperator, isAssignmentOperator) {
+  return Node.isAssignmentOp();
+}
+
 AST_MATCHER(BinaryOperator, isRelationalOperator) {
   return Node.isRelationalOp();
 }
diff --git a/clangd/CMakeLists.txt b/clangd/CMakeLists.txt
index f1c7098..9d037fe 100644
--- a/clangd/CMakeLists.txt
+++ b/clangd/CMakeLists.txt
@@ -10,6 +10,7 @@
   DraftStore.cpp
   GlobalCompilationDatabase.cpp
   JSONRPCDispatcher.cpp
+  Logger.cpp
   Protocol.cpp
   ProtocolHandlers.cpp
 
@@ -18,7 +19,10 @@
   clangBasic
   clangFormat
   clangFrontend
+  clangIndex
+  clangLex
   clangSema
+  clangSerialization
   clangTooling
   clangToolingCore
   ${LLVM_PTHREAD_LIB}
diff --git a/clangd/ClangdLSPServer.cpp b/clangd/ClangdLSPServer.cpp
index fde6b6f..64849de 100644
--- a/clangd/ClangdLSPServer.cpp
+++ b/clangd/ClangdLSPServer.cpp
@@ -9,7 +9,6 @@
 
 #include "ClangdLSPServer.h"
 #include "JSONRPCDispatcher.h"
-#include "ProtocolHandlers.h"
 
 using namespace clang::clangd;
 using namespace clang;
@@ -38,121 +37,86 @@
 
 } // namespace
 
-ClangdLSPServer::LSPDiagnosticsConsumer::LSPDiagnosticsConsumer(
-    ClangdLSPServer &Server)
-    : Server(Server) {}
-
-void ClangdLSPServer::LSPDiagnosticsConsumer::onDiagnosticsReady(
-    PathRef File, Tagged<std::vector<DiagWithFixIts>> Diagnostics) {
-  Server.consumeDiagnostics(File, Diagnostics.Value);
-}
-
-class ClangdLSPServer::LSPProtocolCallbacks : public ProtocolCallbacks {
-public:
-  LSPProtocolCallbacks(ClangdLSPServer &LangServer) : LangServer(LangServer) {}
-
-  void onInitialize(StringRef ID, JSONOutput &Out) override;
-  void onShutdown(JSONOutput &Out) override;
-  void onDocumentDidOpen(DidOpenTextDocumentParams Params,
-                         JSONOutput &Out) override;
-  void onDocumentDidChange(DidChangeTextDocumentParams Params,
-                           JSONOutput &Out) override;
-  void onDocumentDidClose(DidCloseTextDocumentParams Params,
-                          JSONOutput &Out) override;
-  void onDocumentOnTypeFormatting(DocumentOnTypeFormattingParams Params,
-                                  StringRef ID, JSONOutput &Out) override;
-  void onDocumentRangeFormatting(DocumentRangeFormattingParams Params,
-                                 StringRef ID, JSONOutput &Out) override;
-  void onDocumentFormatting(DocumentFormattingParams Params, StringRef ID,
-                            JSONOutput &Out) override;
-  void onCodeAction(CodeActionParams Params, StringRef ID,
-                    JSONOutput &Out) override;
-  void onCompletion(TextDocumentPositionParams Params, StringRef ID,
-                    JSONOutput &Out) override;
-
-private:
-  ClangdLSPServer &LangServer;
-};
-
-void ClangdLSPServer::LSPProtocolCallbacks::onInitialize(StringRef ID,
-                                                         JSONOutput &Out) {
-  Out.writeMessage(
-      R"({"jsonrpc":"2.0","id":)" + ID +
-      R"(,"result":{"capabilities":{
+void ClangdLSPServer::onInitialize(Ctx C, InitializeParams &Params) {
+  C.reply(
+      R"({"capabilities":{
           "textDocumentSync": 1,
           "documentFormattingProvider": true,
           "documentRangeFormattingProvider": true,
           "documentOnTypeFormattingProvider": {"firstTriggerCharacter":"}","moreTriggerCharacter":[]},
           "codeActionProvider": true,
-          "completionProvider": {"resolveProvider": false, "triggerCharacters": [".",">"]}
-        }}})");
+          "completionProvider": {"resolveProvider": false, "triggerCharacters": [".",">",":"]},
+          "signatureHelpProvider": {"triggerCharacters": ["(",","]},
+          "definitionProvider": true
+        }})");
+  if (Params.rootUri && !Params.rootUri->file.empty())
+    Server.setRootPath(Params.rootUri->file);
+  else if (Params.rootPath && !Params.rootPath->empty())
+    Server.setRootPath(*Params.rootPath);
 }
 
-void ClangdLSPServer::LSPProtocolCallbacks::onShutdown(JSONOutput &Out) {
-  LangServer.IsDone = true;
+void ClangdLSPServer::onShutdown(Ctx C, ShutdownParams &Params) {
+  IsDone = true;
 }
 
-void ClangdLSPServer::LSPProtocolCallbacks::onDocumentDidOpen(
-    DidOpenTextDocumentParams Params, JSONOutput &Out) {
-  LangServer.Server.addDocument(Params.textDocument.uri.file,
-                                Params.textDocument.text);
+void ClangdLSPServer::onDocumentDidOpen(Ctx C,
+                                        DidOpenTextDocumentParams &Params) {
+  if (Params.metadata && !Params.metadata->extraFlags.empty())
+    CDB.setExtraFlagsForFile(Params.textDocument.uri.file,
+                             std::move(Params.metadata->extraFlags));
+  Server.addDocument(Params.textDocument.uri.file, Params.textDocument.text);
 }
 
-void ClangdLSPServer::LSPProtocolCallbacks::onDocumentDidChange(
-    DidChangeTextDocumentParams Params, JSONOutput &Out) {
+void ClangdLSPServer::onDocumentDidChange(Ctx C,
+                                          DidChangeTextDocumentParams &Params) {
   // We only support full syncing right now.
-  LangServer.Server.addDocument(Params.textDocument.uri.file,
-                                Params.contentChanges[0].text);
+  Server.addDocument(Params.textDocument.uri.file,
+                     Params.contentChanges[0].text);
 }
 
-void ClangdLSPServer::LSPProtocolCallbacks::onDocumentDidClose(
-    DidCloseTextDocumentParams Params, JSONOutput &Out) {
-  LangServer.Server.removeDocument(Params.textDocument.uri.file);
+void ClangdLSPServer::onFileEvent(Ctx C, DidChangeWatchedFilesParams &Params) {
+  Server.onFileEvent(Params);
 }
 
-void ClangdLSPServer::LSPProtocolCallbacks::onDocumentOnTypeFormatting(
-    DocumentOnTypeFormattingParams Params, StringRef ID, JSONOutput &Out) {
+void ClangdLSPServer::onDocumentDidClose(Ctx C,
+                                         DidCloseTextDocumentParams &Params) {
+  Server.removeDocument(Params.textDocument.uri.file);
+}
+
+void ClangdLSPServer::onDocumentOnTypeFormatting(
+    Ctx C, DocumentOnTypeFormattingParams &Params) {
   auto File = Params.textDocument.uri.file;
-  std::string Code = LangServer.Server.getDocument(File);
-  std::string Edits = replacementsToEdits(
-      Code, LangServer.Server.formatOnType(File, Params.position));
-
-  Out.writeMessage(R"({"jsonrpc":"2.0","id":)" + ID.str() +
-                   R"(,"result":[)" + Edits + R"(]})");
-}
-
-void ClangdLSPServer::LSPProtocolCallbacks::onDocumentRangeFormatting(
-    DocumentRangeFormattingParams Params, StringRef ID, JSONOutput &Out) {
-  auto File = Params.textDocument.uri.file;
-  std::string Code = LangServer.Server.getDocument(File);
-  std::string Edits = replacementsToEdits(
-      Code, LangServer.Server.formatRange(File, Params.range));
-
-  Out.writeMessage(R"({"jsonrpc":"2.0","id":)" + ID.str() +
-                   R"(,"result":[)" + Edits + R"(]})");
-}
-
-void ClangdLSPServer::LSPProtocolCallbacks::onDocumentFormatting(
-    DocumentFormattingParams Params, StringRef ID, JSONOutput &Out) {
-  auto File = Params.textDocument.uri.file;
-  std::string Code = LangServer.Server.getDocument(File);
+  std::string Code = Server.getDocument(File);
   std::string Edits =
-      replacementsToEdits(Code, LangServer.Server.formatFile(File));
-
-  Out.writeMessage(R"({"jsonrpc":"2.0","id":)" + ID.str() +
-                   R"(,"result":[)" + Edits + R"(]})");
+      replacementsToEdits(Code, Server.formatOnType(File, Params.position));
+  C.reply("[" + Edits + "]");
 }
 
-void ClangdLSPServer::LSPProtocolCallbacks::onCodeAction(
-    CodeActionParams Params, StringRef ID, JSONOutput &Out) {
+void ClangdLSPServer::onDocumentRangeFormatting(
+    Ctx C, DocumentRangeFormattingParams &Params) {
+  auto File = Params.textDocument.uri.file;
+  std::string Code = Server.getDocument(File);
+  std::string Edits =
+      replacementsToEdits(Code, Server.formatRange(File, Params.range));
+  C.reply("[" + Edits + "]");
+}
+
+void ClangdLSPServer::onDocumentFormatting(Ctx C,
+                                           DocumentFormattingParams &Params) {
+  auto File = Params.textDocument.uri.file;
+  std::string Code = Server.getDocument(File);
+  std::string Edits = replacementsToEdits(Code, Server.formatFile(File));
+  C.reply("[" + Edits + "]");
+}
+
+void ClangdLSPServer::onCodeAction(Ctx C, CodeActionParams &Params) {
   // We provide a code action for each diagnostic at the requested location
   // which has FixIts available.
-  std::string Code =
-      LangServer.Server.getDocument(Params.textDocument.uri.file);
+  std::string Code = Server.getDocument(Params.textDocument.uri.file);
   std::string Commands;
   for (Diagnostic &D : Params.context.diagnostics) {
     std::vector<clang::tooling::Replacement> Fixes =
-        LangServer.getFixIts(Params.textDocument.uri.file, D);
+        getFixIts(Params.textDocument.uri.file, D);
     std::string Edits = replacementsToEdits(Code, Fixes);
 
     if (!Edits.empty())
@@ -165,19 +129,18 @@
   }
   if (!Commands.empty())
     Commands.pop_back();
-
-  Out.writeMessage(
-      R"({"jsonrpc":"2.0","id":)" + ID.str() +
-      R"(, "result": [)" + Commands +
-      R"(]})");
+  C.reply("[" + Commands + "]");
 }
 
-void ClangdLSPServer::LSPProtocolCallbacks::onCompletion(
-    TextDocumentPositionParams Params, StringRef ID, JSONOutput &Out) {
-
-  auto Items = LangServer.Server.codeComplete(
-      Params.textDocument.uri.file,
-      Position{Params.position.line, Params.position.character}).Value;
+void ClangdLSPServer::onCompletion(Ctx C, TextDocumentPositionParams &Params) {
+  auto Items = Server
+                   .codeComplete(Params.textDocument.uri.file,
+                                 Position{Params.position.line,
+                                          Params.position.character})
+                   .get() // FIXME(ibiryukov): This could be made async if we
+                          // had an API that would allow to attach callbacks to
+                          // futures returned by ClangdServer.
+                   .Value;
 
   std::string Completions;
   for (const auto &Item : Items) {
@@ -186,22 +149,61 @@
   }
   if (!Completions.empty())
     Completions.pop_back();
-  Out.writeMessage(
-      R"({"jsonrpc":"2.0","id":)" + ID.str() +
-      R"(,"result":[)" + Completions + R"(]})");
+  C.reply("[" + Completions + "]");
 }
 
-ClangdLSPServer::ClangdLSPServer(JSONOutput &Out, bool RunSynchronously)
-    : Out(Out), DiagConsumer(*this),
-      Server(CDB, DiagConsumer, FSProvider, RunSynchronously) {}
+void ClangdLSPServer::onSignatureHelp(Ctx C,
+                                      TextDocumentPositionParams &Params) {
+  C.reply(SignatureHelp::unparse(
+      Server
+          .signatureHelp(
+              Params.textDocument.uri.file,
+              Position{Params.position.line, Params.position.character})
+          .Value));
+}
+
+void ClangdLSPServer::onGoToDefinition(Ctx C,
+                                       TextDocumentPositionParams &Params) {
+  auto Items = Server
+                   .findDefinitions(Params.textDocument.uri.file,
+                                    Position{Params.position.line,
+                                             Params.position.character})
+                   .Value;
+
+  std::string Locations;
+  for (const auto &Item : Items) {
+    Locations += Location::unparse(Item);
+    Locations += ",";
+  }
+  if (!Locations.empty())
+    Locations.pop_back();
+  C.reply("[" + Locations + "]");
+}
+
+void ClangdLSPServer::onSwitchSourceHeader(Ctx C,
+                                           TextDocumentIdentifier &Params) {
+  llvm::Optional<Path> Result = Server.switchSourceHeader(Params.uri.file);
+  std::string ResultUri;
+  C.reply(Result ? URI::unparse(URI::fromFile(*Result)) : R"("")");
+}
+
+ClangdLSPServer::ClangdLSPServer(JSONOutput &Out, unsigned AsyncThreadsCount,
+                                 bool SnippetCompletions,
+                                 llvm::Optional<StringRef> ResourceDir,
+                                 llvm::Optional<Path> CompileCommandsDir)
+    : Out(Out), CDB(/*Logger=*/Out, std::move(CompileCommandsDir)),
+      Server(CDB, /*DiagConsumer=*/*this, FSProvider, AsyncThreadsCount,
+             SnippetCompletions, /*Logger=*/Out, ResourceDir) {}
 
 void ClangdLSPServer::run(std::istream &In) {
   assert(!IsDone && "Run was called before");
 
   // Set up JSONRPCDispatcher.
-  LSPProtocolCallbacks Callbacks(*this);
-  JSONRPCDispatcher Dispatcher(llvm::make_unique<Handler>(Out));
-  regiterCallbackHandlers(Dispatcher, Out, Callbacks);
+  JSONRPCDispatcher Dispatcher(
+      [](RequestContext Ctx, llvm::yaml::MappingNode *Params) {
+        Ctx.replyError(-32601, "method not found");
+      });
+  registerCallbackHandlers(Dispatcher, Out, /*Callbacks=*/*this);
 
   // Run the Language Server loop.
   runLanguageServerLoop(In, Out, Dispatcher, IsDone);
@@ -226,12 +228,12 @@
   return FixItsIter->second;
 }
 
-void ClangdLSPServer::consumeDiagnostics(
-    PathRef File, std::vector<DiagWithFixIts> Diagnostics) {
+void ClangdLSPServer::onDiagnosticsReady(
+    PathRef File, Tagged<std::vector<DiagWithFixIts>> Diagnostics) {
   std::string DiagnosticsJSON;
 
   DiagnosticToReplacementMap LocalFixIts; // Temporary storage
-  for (auto &DiagWithFixes : Diagnostics) {
+  for (auto &DiagWithFixes : Diagnostics.Value) {
     auto Diag = DiagWithFixes.Diag;
     DiagnosticsJSON +=
         R"({"range":)" + Range::unparse(Diag.range) +
diff --git a/clangd/ClangdLSPServer.h b/clangd/ClangdLSPServer.h
index e8e66f6..ebddd6b 100644
--- a/clangd/ClangdLSPServer.h
+++ b/clangd/ClangdLSPServer.h
@@ -14,7 +14,9 @@
 #include "GlobalCompilationDatabase.h"
 #include "Path.h"
 #include "Protocol.h"
+#include "ProtocolHandlers.h"
 #include "clang/Tooling/Core/Replacement.h"
+#include "llvm/ADT/Optional.h"
 
 namespace clang {
 namespace clangd {
@@ -23,9 +25,15 @@
 
 /// This class provides implementation of an LSP server, glueing the JSON
 /// dispatch and ClangdServer together.
-class ClangdLSPServer {
+class ClangdLSPServer : private DiagnosticsConsumer, private ProtocolCallbacks {
 public:
-  ClangdLSPServer(JSONOutput &Out, bool RunSynchronously);
+  /// If \p CompileCommandsDir has a value, compile_commands.json will be
+  /// loaded only from \p CompileCommandsDir. Otherwise, clangd will look
+  /// for compile_commands.json in all parent directories of each file.
+  ClangdLSPServer(JSONOutput &Out, unsigned AsyncThreadsCount,
+                  bool SnippetCompletions,
+                  llvm::Optional<StringRef> ResourceDir,
+                  llvm::Optional<Path> CompileCommandsDir);
 
   /// Run LSP server loop, receiving input for it from \p In. \p In must be
   /// opened in binary mode. Output will be written using Out variable passed to
@@ -34,18 +42,30 @@
   void run(std::istream &In);
 
 private:
-  class LSPProtocolCallbacks;
-  class LSPDiagnosticsConsumer : public DiagnosticsConsumer {
-  public:
-    LSPDiagnosticsConsumer(ClangdLSPServer &Server);
+  // Implement DiagnosticsConsumer.
+  virtual void
+  onDiagnosticsReady(PathRef File,
+                     Tagged<std::vector<DiagWithFixIts>> Diagnostics) override;
 
-    virtual void
-    onDiagnosticsReady(PathRef File,
-                       Tagged<std::vector<DiagWithFixIts>> Diagnostics);
-
-  private:
-    ClangdLSPServer &Server;
-  };
+  // Implement ProtocolCallbacks.
+  void onInitialize(Ctx C, InitializeParams &Params) override;
+  void onShutdown(Ctx C, ShutdownParams &Params) override;
+  void onDocumentDidOpen(Ctx C, DidOpenTextDocumentParams &Params) override;
+  void onDocumentDidChange(Ctx C, DidChangeTextDocumentParams &Params) override;
+  void onDocumentDidClose(Ctx C, DidCloseTextDocumentParams &Params) override;
+  void
+  onDocumentOnTypeFormatting(Ctx C,
+                             DocumentOnTypeFormattingParams &Params) override;
+  void
+  onDocumentRangeFormatting(Ctx C,
+                            DocumentRangeFormattingParams &Params) override;
+  void onDocumentFormatting(Ctx C, DocumentFormattingParams &Params) override;
+  void onCodeAction(Ctx C, CodeActionParams &Params) override;
+  void onCompletion(Ctx C, TextDocumentPositionParams &Params) override;
+  void onSignatureHelp(Ctx C, TextDocumentPositionParams &Params) override;
+  void onGoToDefinition(Ctx C, TextDocumentPositionParams &Params) override;
+  void onSwitchSourceHeader(Ctx C, TextDocumentIdentifier &Params) override;
+  void onFileEvent(Ctx C, DidChangeWatchedFilesParams &Params) override;
 
   std::vector<clang::tooling::Replacement>
   getFixIts(StringRef File, const clangd::Diagnostic &D);
@@ -71,7 +91,6 @@
   // Various ClangdServer parameters go here. It's important they're created
   // before ClangdServer.
   DirectoryBasedGlobalCompilationDatabase CDB;
-  LSPDiagnosticsConsumer DiagConsumer;
   RealFileSystemProvider FSProvider;
 
   // Server must be the last member of the class to allow its destructor to exit
diff --git a/clangd/ClangdServer.cpp b/clangd/ClangdServer.cpp
index 73c1ae5..0af9e6f 100644
--- a/clangd/ClangdServer.cpp
+++ b/clangd/ClangdServer.cpp
@@ -9,12 +9,12 @@
 
 #include "ClangdServer.h"
 #include "clang/Format/Format.h"
-#include "clang/Frontend/ASTUnit.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/CompilerInvocation.h"
 #include "clang/Tooling/CompilationDatabase.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
 #include "llvm/Support/raw_ostream.h"
 #include <future>
 
@@ -23,6 +23,16 @@
 
 namespace {
 
+class FulfillPromiseGuard {
+public:
+  FulfillPromiseGuard(std::promise<void> &Promise) : Promise(Promise) {}
+
+  ~FulfillPromiseGuard() { Promise.set_value(); }
+
+private:
+  std::promise<void> &Promise;
+};
+
 std::vector<tooling::Replacement> formatCode(StringRef Code, StringRef Filename,
                                              ArrayRef<tooling::Range> Ranges) {
   // Call clang-format.
@@ -33,6 +43,11 @@
   return std::vector<tooling::Replacement>(Result.begin(), Result.end());
 }
 
+std::string getStandardResourceDir() {
+  static int Dummy; // Just an address in this process.
+  return CompilerInvocation::GetResourcesPath("clangd", (void *)&Dummy);
+}
+
 } // namespace
 
 size_t clangd::positionToOffset(StringRef Code, Position P) {
@@ -63,40 +78,52 @@
   return make_tagged(vfs::getRealFileSystem(), VFSTag());
 }
 
-ClangdScheduler::ClangdScheduler(bool RunSynchronously)
-    : RunSynchronously(RunSynchronously) {
+unsigned clangd::getDefaultAsyncThreadsCount() {
+  unsigned HardwareConcurrency = std::thread::hardware_concurrency();
+  // C++ standard says that hardware_concurrency()
+  // may return 0, fallback to 1 worker thread in
+  // that case.
+  if (HardwareConcurrency == 0)
+    return 1;
+  return HardwareConcurrency;
+}
+
+ClangdScheduler::ClangdScheduler(unsigned AsyncThreadsCount)
+    : RunSynchronously(AsyncThreadsCount == 0) {
   if (RunSynchronously) {
     // Don't start the worker thread if we're running synchronously
     return;
   }
 
-  // Initialize Worker in ctor body, rather than init list to avoid potentially
-  // using not-yet-initialized members
-  Worker = std::thread([this]() {
-    while (true) {
-      std::function<void()> Request;
+  Workers.reserve(AsyncThreadsCount);
+  for (unsigned I = 0; I < AsyncThreadsCount; ++I) {
+    Workers.push_back(std::thread([this]() {
+      while (true) {
+        UniqueFunction<void()> Request;
 
-      // Pick request from the queue
-      {
-        std::unique_lock<std::mutex> Lock(Mutex);
-        // Wait for more requests.
-        RequestCV.wait(Lock, [this] { return !RequestQueue.empty() || Done; });
-        if (Done)
-          return;
+        // Pick request from the queue
+        {
+          std::unique_lock<std::mutex> Lock(Mutex);
+          // Wait for more requests.
+          RequestCV.wait(Lock,
+                         [this] { return !RequestQueue.empty() || Done; });
+          if (Done)
+            return;
 
-        assert(!RequestQueue.empty() && "RequestQueue was empty");
+          assert(!RequestQueue.empty() && "RequestQueue was empty");
 
-        // We process requests starting from the front of the queue. Users of
-        // ClangdScheduler have a way to prioritise their requests by putting
-        // them to the either side of the queue (using either addToEnd or
-        // addToFront).
-        Request = std::move(RequestQueue.front());
-        RequestQueue.pop_front();
-      } // unlock Mutex
+          // We process requests starting from the front of the queue. Users of
+          // ClangdScheduler have a way to prioritise their requests by putting
+          // them to the either side of the queue (using either addToEnd or
+          // addToFront).
+          Request = std::move(RequestQueue.front());
+          RequestQueue.pop_front();
+        } // unlock Mutex
 
-      Request();
-    }
-  });
+        Request();
+      }
+    }));
+  }
 }
 
 ClangdScheduler::~ClangdScheduler() {
@@ -108,104 +135,145 @@
     // Wake up the worker thread
     Done = true;
   } // unlock Mutex
-  RequestCV.notify_one();
-  Worker.join();
-}
+  RequestCV.notify_all();
 
-void ClangdScheduler::addToFront(std::function<void()> Request) {
-  if (RunSynchronously) {
-    Request();
-    return;
-  }
-
-  {
-    std::lock_guard<std::mutex> Lock(Mutex);
-    RequestQueue.push_front(Request);
-  }
-  RequestCV.notify_one();
-}
-
-void ClangdScheduler::addToEnd(std::function<void()> Request) {
-  if (RunSynchronously) {
-    Request();
-    return;
-  }
-
-  {
-    std::lock_guard<std::mutex> Lock(Mutex);
-    RequestQueue.push_back(Request);
-  }
-  RequestCV.notify_one();
+  for (auto &Worker : Workers)
+    Worker.join();
 }
 
 ClangdServer::ClangdServer(GlobalCompilationDatabase &CDB,
                            DiagnosticsConsumer &DiagConsumer,
                            FileSystemProvider &FSProvider,
-                           bool RunSynchronously)
-    : CDB(CDB), DiagConsumer(DiagConsumer), FSProvider(FSProvider),
+                           unsigned AsyncThreadsCount, bool SnippetCompletions,
+                           clangd::Logger &Logger,
+                           llvm::Optional<StringRef> ResourceDir)
+    : Logger(Logger), CDB(CDB), DiagConsumer(DiagConsumer),
+      FSProvider(FSProvider),
+      ResourceDir(ResourceDir ? ResourceDir->str() : getStandardResourceDir()),
       PCHs(std::make_shared<PCHContainerOperations>()),
-      WorkScheduler(RunSynchronously) {}
+      SnippetCompletions(SnippetCompletions), WorkScheduler(AsyncThreadsCount) {
+}
 
-void ClangdServer::addDocument(PathRef File, StringRef Contents) {
+void ClangdServer::setRootPath(PathRef RootPath) {
+  std::string NewRootPath = llvm::sys::path::convert_to_slash(
+      RootPath, llvm::sys::path::Style::posix);
+  if (llvm::sys::fs::is_directory(NewRootPath))
+    this->RootPath = NewRootPath;
+}
+
+std::future<void> ClangdServer::addDocument(PathRef File, StringRef Contents) {
   DocVersion Version = DraftMgr.updateDraft(File, Contents);
-  Path FileStr = File;
-  WorkScheduler.addToFront([this, FileStr, Version]() {
-    auto FileContents = DraftMgr.getDraft(FileStr);
-    if (FileContents.Version != Version)
-      return; // This request is outdated, do nothing
 
-    assert(FileContents.Draft &&
-           "No contents inside a file that was scheduled for reparse");
-    auto TaggedFS = FSProvider.getTaggedFileSystem(FileStr);
-    Units.runOnUnit(
-        FileStr, *FileContents.Draft, CDB, PCHs, TaggedFS.Value,
-        [&](ClangdUnit const &Unit) {
-          DiagConsumer.onDiagnosticsReady(
-              FileStr, make_tagged(Unit.getLocalDiagnostics(), TaggedFS.Tag));
-        });
-  });
+  auto TaggedFS = FSProvider.getTaggedFileSystem(File);
+  std::shared_ptr<CppFile> Resources = Units.getOrCreateFile(
+      File, ResourceDir, CDB, PCHs, TaggedFS.Value, Logger);
+  return scheduleReparseAndDiags(File, VersionedDraft{Version, Contents.str()},
+                                 std::move(Resources), std::move(TaggedFS));
 }
 
-void ClangdServer::removeDocument(PathRef File) {
-  auto Version = DraftMgr.removeDraft(File);
-  Path FileStr = File;
-  WorkScheduler.addToFront([this, FileStr, Version]() {
-    if (Version != DraftMgr.getVersion(FileStr))
-      return; // This request is outdated, do nothing
-
-    Units.removeUnitIfPresent(FileStr);
-  });
+std::future<void> ClangdServer::removeDocument(PathRef File) {
+  DraftMgr.removeDraft(File);
+  std::shared_ptr<CppFile> Resources = Units.removeIfPresent(File);
+  return scheduleCancelRebuild(std::move(Resources));
 }
 
-void ClangdServer::forceReparse(PathRef File) {
-  // The addDocument schedules the reparse even if the contents of the file
-  // never changed, so we just call it here.
-  addDocument(File, getDocument(File));
+std::future<void> ClangdServer::forceReparse(PathRef File) {
+  auto FileContents = DraftMgr.getDraft(File);
+  assert(FileContents.Draft &&
+         "forceReparse() was called for non-added document");
+
+  auto TaggedFS = FSProvider.getTaggedFileSystem(File);
+  auto Recreated = Units.recreateFileIfCompileCommandChanged(
+      File, ResourceDir, CDB, PCHs, TaggedFS.Value, Logger);
+
+  // Note that std::future from this cleanup action is ignored.
+  scheduleCancelRebuild(std::move(Recreated.RemovedFile));
+  // Schedule a reparse.
+  return scheduleReparseAndDiags(File, std::move(FileContents),
+                                 std::move(Recreated.FileInCollection),
+                                 std::move(TaggedFS));
 }
 
-Tagged<std::vector<CompletionItem>>
+std::future<Tagged<std::vector<CompletionItem>>>
 ClangdServer::codeComplete(PathRef File, Position Pos,
-                           llvm::Optional<StringRef> OverridenContents) {
+                           llvm::Optional<StringRef> OverridenContents,
+                           IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS) {
+  std::string Contents;
+  if (OverridenContents) {
+    Contents = *OverridenContents;
+  } else {
+    auto FileContents = DraftMgr.getDraft(File);
+    assert(FileContents.Draft &&
+           "codeComplete is called for non-added document");
+
+    Contents = std::move(*FileContents.Draft);
+  }
+
+  auto TaggedFS = FSProvider.getTaggedFileSystem(File);
+  if (UsedFS)
+    *UsedFS = TaggedFS.Value;
+
+  std::shared_ptr<CppFile> Resources = Units.getFile(File);
+  assert(Resources && "Calling completion on non-added file");
+
+  using PackagedTask =
+      std::packaged_task<Tagged<std::vector<CompletionItem>>()>;
+
+  // Remember the current Preamble and use it when async task starts executing.
+  // At the point when async task starts executing, we may have a different
+  // Preamble in Resources. However, we assume the Preamble that we obtain here
+  // is reusable in completion more often.
+  std::shared_ptr<const PreambleData> Preamble =
+      Resources->getPossiblyStalePreamble();
+  // A task that will be run asynchronously.
+  PackagedTask Task([=]() mutable { // 'mutable' to reassign Preamble variable.
+    if (!Preamble) {
+      // Maybe we built some preamble before processing this request.
+      Preamble = Resources->getPossiblyStalePreamble();
+    }
+    // FIXME(ibiryukov): even if Preamble is non-null, we may want to check
+    // both the old and the new version in case only one of them matches.
+
+    std::vector<CompletionItem> Result = clangd::codeComplete(
+        File, Resources->getCompileCommand(),
+        Preamble ? &Preamble->Preamble : nullptr, Contents, Pos, TaggedFS.Value,
+        PCHs, SnippetCompletions, Logger);
+    return make_tagged(std::move(Result), std::move(TaggedFS.Tag));
+  });
+
+  auto Future = Task.get_future();
+  // FIXME(ibiryukov): to reduce overhead for wrapping the same callable
+  // multiple times, ClangdScheduler should return future<> itself.
+  WorkScheduler.addToFront([](PackagedTask Task) { Task(); }, std::move(Task));
+  return Future;
+}
+
+Tagged<SignatureHelp>
+ClangdServer::signatureHelp(PathRef File, Position Pos,
+                            llvm::Optional<StringRef> OverridenContents,
+                            IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS) {
   std::string DraftStorage;
   if (!OverridenContents) {
     auto FileContents = DraftMgr.getDraft(File);
     assert(FileContents.Draft &&
-           "codeComplete is called for non-added document");
+           "signatureHelp is called for non-added document");
 
     DraftStorage = std::move(*FileContents.Draft);
     OverridenContents = DraftStorage;
   }
 
-  std::vector<CompletionItem> Result;
   auto TaggedFS = FSProvider.getTaggedFileSystem(File);
-  // It would be nice to use runOnUnitWithoutReparse here, but we can't
-  // guarantee the correctness of code completion cache here if we don't do the
-  // reparse.
-  Units.runOnUnit(File, *OverridenContents, CDB, PCHs, TaggedFS.Value,
-                  [&](ClangdUnit &Unit) {
-                    Result = Unit.codeComplete(*OverridenContents, Pos,
-                                               TaggedFS.Value);
-                  });
+  if (UsedFS)
+    *UsedFS = TaggedFS.Value;
+
+  std::shared_ptr<CppFile> Resources = Units.getFile(File);
+  assert(Resources && "Calling signatureHelp on non-added file");
+
+  auto Preamble = Resources->getPossiblyStalePreamble();
+  auto Result = clangd::signatureHelp(File, Resources->getCompileCommand(),
+                                      Preamble ? &Preamble->Preamble : nullptr,
+                                      *OverridenContents, Pos, TaggedFS.Value,
+                                      PCHs, Logger);
   return make_tagged(std::move(Result), TaggedFS.Tag);
 }
 
@@ -245,22 +313,173 @@
 }
 
 std::string ClangdServer::dumpAST(PathRef File) {
-  std::promise<std::string> DumpPromise;
-  auto DumpFuture = DumpPromise.get_future();
-  auto Version = DraftMgr.getVersion(File);
+  std::shared_ptr<CppFile> Resources = Units.getFile(File);
+  assert(Resources && "dumpAST is called for non-added document");
 
-  WorkScheduler.addToEnd([this, &DumpPromise, File, Version]() {
-    assert(DraftMgr.getVersion(File) == Version && "Version has changed");
-
-    Units.runOnExistingUnit(File, [&DumpPromise](ClangdUnit &Unit) {
-      std::string Result;
-
-      llvm::raw_string_ostream ResultOS(Result);
-      Unit.dumpAST(ResultOS);
-      ResultOS.flush();
-
-      DumpPromise.set_value(std::move(Result));
-    });
+  std::string Result;
+  Resources->getAST().get()->runUnderLock([&Result](ParsedAST *AST) {
+    llvm::raw_string_ostream ResultOS(Result);
+    if (AST) {
+      clangd::dumpAST(*AST, ResultOS);
+    } else {
+      ResultOS << "<no-ast>";
+    }
+    ResultOS.flush();
   });
-  return DumpFuture.get();
+  return Result;
+}
+
+Tagged<std::vector<Location>> ClangdServer::findDefinitions(PathRef File,
+                                                            Position Pos) {
+  auto FileContents = DraftMgr.getDraft(File);
+  assert(FileContents.Draft &&
+         "findDefinitions is called for non-added document");
+
+  auto TaggedFS = FSProvider.getTaggedFileSystem(File);
+
+  std::shared_ptr<CppFile> Resources = Units.getFile(File);
+  assert(Resources && "Calling findDefinitions on non-added file");
+
+  std::vector<Location> Result;
+  Resources->getAST().get()->runUnderLock([Pos, &Result, this](ParsedAST *AST) {
+    if (!AST)
+      return;
+    Result = clangd::findDefinitions(*AST, Pos, Logger);
+  });
+  return make_tagged(std::move(Result), TaggedFS.Tag);
+}
+
+llvm::Optional<Path> ClangdServer::switchSourceHeader(PathRef Path) {
+
+  StringRef SourceExtensions[] = {".cpp", ".c", ".cc", ".cxx",
+                                  ".c++", ".m", ".mm"};
+  StringRef HeaderExtensions[] = {".h", ".hh", ".hpp", ".hxx", ".inc"};
+
+  StringRef PathExt = llvm::sys::path::extension(Path);
+
+  // Lookup in a list of known extensions.
+  auto SourceIter =
+      std::find_if(std::begin(SourceExtensions), std::end(SourceExtensions),
+                   [&PathExt](PathRef SourceExt) {
+                     return SourceExt.equals_lower(PathExt);
+                   });
+  bool IsSource = SourceIter != std::end(SourceExtensions);
+
+  auto HeaderIter =
+      std::find_if(std::begin(HeaderExtensions), std::end(HeaderExtensions),
+                   [&PathExt](PathRef HeaderExt) {
+                     return HeaderExt.equals_lower(PathExt);
+                   });
+
+  bool IsHeader = HeaderIter != std::end(HeaderExtensions);
+
+  // We can only switch between extensions known extensions.
+  if (!IsSource && !IsHeader)
+    return llvm::None;
+
+  // Array to lookup extensions for the switch. An opposite of where original
+  // extension was found.
+  ArrayRef<StringRef> NewExts;
+  if (IsSource)
+    NewExts = HeaderExtensions;
+  else
+    NewExts = SourceExtensions;
+
+  // Storage for the new path.
+  SmallString<128> NewPath = StringRef(Path);
+
+  // Instance of vfs::FileSystem, used for file existence checks.
+  auto FS = FSProvider.getTaggedFileSystem(Path).Value;
+
+  // Loop through switched extension candidates.
+  for (StringRef NewExt : NewExts) {
+    llvm::sys::path::replace_extension(NewPath, NewExt);
+    if (FS->exists(NewPath))
+      return NewPath.str().str(); // First str() to convert from SmallString to
+                                  // StringRef, second to convert from StringRef
+                                  // to std::string
+
+    // Also check NewExt in upper-case, just in case.
+    llvm::sys::path::replace_extension(NewPath, NewExt.upper());
+    if (FS->exists(NewPath))
+      return NewPath.str().str();
+  }
+
+  return llvm::None;
+}
+
+std::future<void> ClangdServer::scheduleReparseAndDiags(
+    PathRef File, VersionedDraft Contents, std::shared_ptr<CppFile> Resources,
+    Tagged<IntrusiveRefCntPtr<vfs::FileSystem>> TaggedFS) {
+
+  assert(Contents.Draft && "Draft must have contents");
+  UniqueFunction<llvm::Optional<std::vector<DiagWithFixIts>>()>
+      DeferredRebuild =
+          Resources->deferRebuild(*Contents.Draft, TaggedFS.Value);
+  std::promise<void> DonePromise;
+  std::future<void> DoneFuture = DonePromise.get_future();
+
+  DocVersion Version = Contents.Version;
+  Path FileStr = File;
+  VFSTag Tag = TaggedFS.Tag;
+  auto ReparseAndPublishDiags =
+      [this, FileStr, Version,
+       Tag](UniqueFunction<llvm::Optional<std::vector<DiagWithFixIts>>()>
+                DeferredRebuild,
+            std::promise<void> DonePromise) -> void {
+    FulfillPromiseGuard Guard(DonePromise);
+
+    auto CurrentVersion = DraftMgr.getVersion(FileStr);
+    if (CurrentVersion != Version)
+      return; // This request is outdated
+
+    auto Diags = DeferredRebuild();
+    if (!Diags)
+      return; // A new reparse was requested before this one completed.
+
+    // We need to serialize access to resulting diagnostics to avoid calling
+    // `onDiagnosticsReady` in the wrong order.
+    std::lock_guard<std::mutex> DiagsLock(DiagnosticsMutex);
+    DocVersion &LastReportedDiagsVersion = ReportedDiagnosticVersions[FileStr];
+    // FIXME(ibiryukov): get rid of '<' comparison here. In the current
+    // implementation diagnostics will not be reported after version counters'
+    // overflow. This should not happen in practice, since DocVersion is a
+    // 64-bit unsigned integer.
+    if (Version < LastReportedDiagsVersion)
+      return;
+    LastReportedDiagsVersion = Version;
+
+    DiagConsumer.onDiagnosticsReady(FileStr,
+                                    make_tagged(std::move(*Diags), Tag));
+  };
+
+  WorkScheduler.addToFront(std::move(ReparseAndPublishDiags),
+                           std::move(DeferredRebuild), std::move(DonePromise));
+  return DoneFuture;
+}
+
+std::future<void>
+ClangdServer::scheduleCancelRebuild(std::shared_ptr<CppFile> Resources) {
+  std::promise<void> DonePromise;
+  std::future<void> DoneFuture = DonePromise.get_future();
+  if (!Resources) {
+    // No need to schedule any cleanup.
+    DonePromise.set_value();
+    return DoneFuture;
+  }
+
+  UniqueFunction<void()> DeferredCancel = Resources->deferCancelRebuild();
+  auto CancelReparses = [Resources](std::promise<void> DonePromise,
+                                    UniqueFunction<void()> DeferredCancel) {
+    FulfillPromiseGuard Guard(DonePromise);
+    DeferredCancel();
+  };
+  WorkScheduler.addToFront(std::move(CancelReparses), std::move(DonePromise),
+                           std::move(DeferredCancel));
+  return DoneFuture;
+}
+
+void ClangdServer::onFileEvent(const DidChangeWatchedFilesParams &Params) {
+  // FIXME: Do nothing for now. This will be used for indexing and potentially
+  // invalidating other caches.
 }
diff --git a/clangd/ClangdServer.h b/clangd/ClangdServer.h
index e989842..f2023f8 100644
--- a/clangd/ClangdServer.h
+++ b/clangd/ClangdServer.h
@@ -13,7 +13,6 @@
 #include "ClangdUnitStore.h"
 #include "DraftStore.h"
 #include "GlobalCompilationDatabase.h"
-#include "clang/Frontend/ASTUnit.h"
 #include "clang/Tooling/CompilationDatabase.h"
 #include "clang/Tooling/Core/Replacement.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -21,6 +20,7 @@
 #include "llvm/ADT/StringRef.h"
 
 #include "ClangdUnit.h"
+#include "Function.h"
 #include "Protocol.h"
 
 #include <condition_variable>
@@ -36,6 +36,8 @@
 
 namespace clangd {
 
+class Logger;
+
 /// Turn a [line, column] pair into an offset in Code.
 size_t positionToOffset(StringRef Code, Position P);
 
@@ -49,6 +51,9 @@
 /// FileSystemProvider when this value was computed.
 template <class T> class Tagged {
 public:
+  // MSVC requires future<> arguments to be default-constructible.
+  Tagged() = default;
+
   template <class U>
   Tagged(U &&Value, VFSTag Tag)
       : Value(std::forward<U>(Value)), Tag(std::move(Tag)) {}
@@ -60,13 +65,13 @@
   Tagged(Tagged<U> &&Other)
       : Value(std::move(Other.Value)), Tag(std::move(Other.Tag)) {}
 
-  T Value;
-  VFSTag Tag;
+  T Value = T();
+  VFSTag Tag = VFSTag();
 };
 
 template <class T>
 Tagged<typename std::decay<T>::type> make_tagged(T &&Value, VFSTag Tag) {
-  return Tagged<T>(std::forward<T>(Value), Tag);
+  return Tagged<typename std::decay<T>::type>(std::forward<T>(Value), Tag);
 }
 
 class DiagnosticsConsumer {
@@ -101,79 +106,170 @@
 
 class ClangdServer;
 
-/// Handles running WorkerRequests of ClangdServer on a separate threads.
-/// Currently runs only one worker thread.
+/// Returns a number of a default async threads to use for ClangdScheduler.
+/// Returned value is always >= 1 (i.e. will not cause requests to be processed
+/// synchronously).
+unsigned getDefaultAsyncThreadsCount();
+
+/// Handles running WorkerRequests of ClangdServer on a number of worker
+/// threads.
 class ClangdScheduler {
 public:
-  ClangdScheduler(bool RunSynchronously);
+  /// If \p AsyncThreadsCount is 0, requests added using addToFront and addToEnd
+  /// will be processed synchronously on the calling thread.
+  // Otherwise, \p AsyncThreadsCount threads will be created to schedule the
+  // requests.
+  ClangdScheduler(unsigned AsyncThreadsCount);
   ~ClangdScheduler();
 
-  /// Add \p Request to the start of the queue. \p Request will be run on a
-  /// separate worker thread.
-  /// \p Request is scheduled to be executed before all currently added
-  /// requests.
-  void addToFront(std::function<void()> Request);
-  /// Add \p Request to the end of the queue. \p Request will be run on a
-  /// separate worker thread.
-  /// \p Request is scheduled to be executed after all currently added
-  /// requests.
-  void addToEnd(std::function<void()> Request);
+  /// Add a new request to run function \p F with args \p As to the start of the
+  /// queue. The request will be run on a separate thread.
+  template <class Func, class... Args>
+  void addToFront(Func &&F, Args &&... As) {
+    if (RunSynchronously) {
+      std::forward<Func>(F)(std::forward<Args>(As)...);
+      return;
+    }
+
+    {
+      std::lock_guard<std::mutex> Lock(Mutex);
+      RequestQueue.push_front(
+          BindWithForward(std::forward<Func>(F), std::forward<Args>(As)...));
+    }
+    RequestCV.notify_one();
+  }
+
+  /// Add a new request to run function \p F with args \p As to the end of the
+  /// queue. The request will be run on a separate thread.
+  template <class Func, class... Args> void addToEnd(Func &&F, Args &&... As) {
+    if (RunSynchronously) {
+      std::forward<Func>(F)(std::forward<Args>(As)...);
+      return;
+    }
+
+    {
+      std::lock_guard<std::mutex> Lock(Mutex);
+      RequestQueue.push_back(
+          BindWithForward(std::forward<Func>(F), std::forward<Args>(As)...));
+    }
+    RequestCV.notify_one();
+  }
 
 private:
   bool RunSynchronously;
   std::mutex Mutex;
-  /// We run some tasks on a separate thread(parsing, ClangdUnit cleanup).
-  /// This thread looks into RequestQueue to find requests to handle and
-  /// terminates when Done is set to true.
-  std::thread Worker;
-  /// Setting Done to true will make the worker thread terminate.
+  /// We run some tasks on separate threads(parsing, CppFile cleanup).
+  /// These threads looks into RequestQueue to find requests to handle and
+  /// terminate when Done is set to true.
+  std::vector<std::thread> Workers;
+  /// Setting Done to true will make the worker threads terminate.
   bool Done = false;
-  /// A queue of requests.
-  /// FIXME(krasimir): code completion should always have priority over parsing
-  /// for diagnostics.
-  std::deque<std::function<void()>> RequestQueue;
-  /// Condition variable to wake up the worker thread.
+  /// A queue of requests. Elements of this vector are async computations (i.e.
+  /// results of calling std::async(std::launch::deferred, ...)).
+  std::deque<UniqueFunction<void()>> RequestQueue;
+  /// Condition variable to wake up worker threads.
   std::condition_variable RequestCV;
 };
 
 /// Provides API to manage ASTs for a collection of C++ files and request
-/// various language features(currently, only codeCompletion and async
-/// diagnostics for tracked files).
+/// various language features.
+/// Currently supports async diagnostics, code completion, formatting and goto
+/// definition.
 class ClangdServer {
 public:
-  /// Creates a new ClangdServer. If \p RunSynchronously is false, no worker
-  /// thread will be created and all requests will be completed synchronously on
-  /// the calling thread (this is mostly used for tests). If \p RunSynchronously
-  /// is true, a worker thread will be created to parse files in the background
-  /// and provide diagnostics results via DiagConsumer.onDiagnosticsReady
-  /// callback. File accesses for each instance of parsing will be conducted via
-  /// a vfs::FileSystem provided by \p FSProvider. Results of code
-  /// completion/diagnostics also include a tag, that \p FSProvider returns
-  /// along with the vfs::FileSystem.
+  /// Creates a new ClangdServer instance.
+  /// To process parsing requests asynchronously, ClangdServer will spawn \p
+  /// AsyncThreadsCount worker threads. However, if \p AsyncThreadsCount is 0,
+  /// all requests will be processed on the calling thread.
+  ///
+  /// When \p SnippetCompletions is true, completion items will be presented
+  /// with embedded snippets. Otherwise, plaintext items will be presented.
+  ///
+  /// ClangdServer uses \p FSProvider to get an instance of vfs::FileSystem for
+  /// each parsing request. Results of code completion and diagnostics also
+  /// include a tag, that \p FSProvider returns along with the vfs::FileSystem.
+  ///
+  /// The value of \p ResourceDir will be used to search for internal headers
+  /// (overriding defaults and -resource-dir compiler flag). If \p ResourceDir
+  /// is None, ClangdServer will call CompilerInvocation::GetResourcePath() to
+  /// obtain the standard resource directory.
+  ///
+  /// ClangdServer uses \p CDB to obtain compilation arguments for parsing. Note
+  /// that ClangdServer only obtains compilation arguments once for each newly
+  /// added file (i.e., when processing a first call to addDocument) and reuses
+  /// those arguments for subsequent reparses. However, ClangdServer will check
+  /// if compilation arguments changed on calls to forceReparse().
+  ///
+  /// After each parsing request finishes, ClangdServer reports diagnostics to
+  /// \p DiagConsumer. Note that a callback to \p DiagConsumer happens on a
+  /// worker thread. Therefore, instances of \p DiagConsumer must properly
+  /// synchronize access to shared state.
+  ///
+  /// Various messages are logged using \p Logger.
   ClangdServer(GlobalCompilationDatabase &CDB,
                DiagnosticsConsumer &DiagConsumer,
-               FileSystemProvider &FSProvider, bool RunSynchronously);
+               FileSystemProvider &FSProvider, unsigned AsyncThreadsCount,
+               bool SnippetCompletions, clangd::Logger &Logger,
+               llvm::Optional<StringRef> ResourceDir = llvm::None);
+
+  /// Set the root path of the workspace.
+  void setRootPath(PathRef RootPath);
 
   /// Add a \p File to the list of tracked C++ files or update the contents if
   /// \p File is already tracked. Also schedules parsing of the AST for it on a
   /// separate thread. When the parsing is complete, DiagConsumer passed in
   /// constructor will receive onDiagnosticsReady callback.
-  void addDocument(PathRef File, StringRef Contents);
+  /// \return A future that will become ready when the rebuild (including
+  /// diagnostics) is finished.
+  std::future<void> addDocument(PathRef File, StringRef Contents);
   /// Remove \p File from list of tracked files, schedule a request to free
   /// resources associated with it.
-  void removeDocument(PathRef File);
+  /// \return A future that will become ready when the file is removed and all
+  /// associated resources are freed.
+  std::future<void> removeDocument(PathRef File);
   /// Force \p File to be reparsed using the latest contents.
-  void forceReparse(PathRef File);
+  /// Will also check if CompileCommand, provided by GlobalCompilationDatabase
+  /// for \p File has changed. If it has, will remove currently stored Preamble
+  /// and AST and rebuild them from scratch.
+  std::future<void> forceReparse(PathRef File);
 
-  /// Run code completion for \p File at \p Pos. If \p OverridenContents is not
-  /// None, they will used only for code completion, i.e. no diagnostics update
-  /// will be scheduled and a draft for \p File will not be updated.
-  /// If \p OverridenContents is None, contents of the current draft for \p File
-  /// will be used.
-  /// This method should only be called for currently tracked files.
-  Tagged<std::vector<CompletionItem>>
+  /// Run code completion for \p File at \p Pos.
+  ///
+  /// Request is processed asynchronously. You can use the returned future to
+  /// wait for the results of the async request.
+  ///
+  /// If \p OverridenContents is not None, they will used only for code
+  /// completion, i.e. no diagnostics update will be scheduled and a draft for
+  /// \p File will not be updated. If \p OverridenContents is None, contents of
+  /// the current draft for \p File will be used. If \p UsedFS is non-null, it
+  /// will be overwritten by vfs::FileSystem used for completion.
+  ///
+  /// This method should only be called for currently tracked files. However, it
+  /// is safe to call removeDocument for \p File after this method returns, even
+  /// while returned future is not yet ready.
+  std::future<Tagged<std::vector<CompletionItem>>>
   codeComplete(PathRef File, Position Pos,
-               llvm::Optional<StringRef> OverridenContents = llvm::None);
+               llvm::Optional<StringRef> OverridenContents = llvm::None,
+               IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS = nullptr);
+
+  /// Provide signature help for \p File at \p Pos. If \p OverridenContents is
+  /// not None, they will used only for signature help, i.e. no diagnostics
+  /// update will be scheduled and a draft for \p File will not be updated. If
+  /// \p OverridenContents is None, contents of the current draft for \p File
+  /// will be used. If \p UsedFS is non-null, it will be overwritten by
+  /// vfs::FileSystem used for signature help. This method should only be called
+  /// for currently tracked files.
+  Tagged<SignatureHelp>
+  signatureHelp(PathRef File, Position Pos,
+                llvm::Optional<StringRef> OverridenContents = llvm::None,
+                IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS = nullptr);
+
+  /// Get definition of symbol at a specified \p Line and \p Column in \p File.
+  Tagged<std::vector<Location>> findDefinitions(PathRef File, Position Pos);
+
+  /// Helper function that returns a path to the corresponding source file when
+  /// given a header file and vice versa.
+  llvm::Optional<Path> switchSourceHeader(PathRef Path);
 
   /// Run formatting for \p Rng inside \p File.
   std::vector<tooling::Replacement> formatRange(PathRef File, Range Rng);
@@ -192,14 +288,34 @@
   /// Waits until all requests to worker thread are finished and dumps AST for
   /// \p File. \p File must be in the list of added documents.
   std::string dumpAST(PathRef File);
+  /// Called when an event occurs for a watched file in the workspace.
+  void onFileEvent(const DidChangeWatchedFilesParams &Params);
 
 private:
+  std::future<void>
+  scheduleReparseAndDiags(PathRef File, VersionedDraft Contents,
+                          std::shared_ptr<CppFile> Resources,
+                          Tagged<IntrusiveRefCntPtr<vfs::FileSystem>> TaggedFS);
+
+  std::future<void> scheduleCancelRebuild(std::shared_ptr<CppFile> Resources);
+
+  clangd::Logger &Logger;
   GlobalCompilationDatabase &CDB;
   DiagnosticsConsumer &DiagConsumer;
   FileSystemProvider &FSProvider;
   DraftStore DraftMgr;
-  ClangdUnitStore Units;
+  CppFileCollection Units;
+  std::string ResourceDir;
+  // If set, this represents the workspace path.
+  llvm::Optional<std::string> RootPath;
   std::shared_ptr<PCHContainerOperations> PCHs;
+  bool SnippetCompletions;
+  /// Used to serialize diagnostic callbacks.
+  /// FIXME(ibiryukov): get rid of an extra map and put all version counters
+  /// into CppFile.
+  std::mutex DiagnosticsMutex;
+  /// Maps from a filename to the latest version of reported diagnostics.
+  llvm::StringMap<DocVersion> ReportedDiagnosticVersions;
   // WorkScheduler has to be the last member, because its destructor has to be
   // called before all other members to stop the worker thread that references
   // ClangdServer
diff --git a/clangd/ClangdUnit.cpp b/clangd/ClangdUnit.cpp
index 218b2c7..a476eeb 100644
--- a/clangd/ClangdUnit.cpp
+++ b/clangd/ClangdUnit.cpp
@@ -8,70 +8,264 @@
 //===---------------------------------------------------------------------===//
 
 #include "ClangdUnit.h"
-#include "clang/Frontend/ASTUnit.h"
+
+#include "Logger.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/FrontendActions.h"
 #include "clang/Frontend/Utils.h"
+#include "clang/Index/IndexDataConsumer.h"
+#include "clang/Index/IndexingAction.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Serialization/ASTWriter.h"
 #include "clang/Tooling/CompilationDatabase.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/CrashRecoveryContext.h"
 #include "llvm/Support/Format.h"
 
+#include <algorithm>
+#include <chrono>
+
 using namespace clang::clangd;
 using namespace clang;
 
-ClangdUnit::ClangdUnit(PathRef FileName, StringRef Contents,
-                       std::shared_ptr<PCHContainerOperations> PCHs,
-                       std::vector<tooling::CompileCommand> Commands,
-                       IntrusiveRefCntPtr<vfs::FileSystem> VFS)
-    : FileName(FileName), PCHs(PCHs) {
-  assert(!Commands.empty() && "No compile commands provided");
+namespace {
 
-  // Inject the resource dir.
-  // FIXME: Don't overwrite it if it's already there.
-  static int Dummy; // Just an address in this process.
-  std::string ResourceDir =
-      CompilerInvocation::GetResourcesPath("clangd", (void *)&Dummy);
-  Commands.front().CommandLine.push_back("-resource-dir=" + ResourceDir);
+class DeclTrackingASTConsumer : public ASTConsumer {
+public:
+  DeclTrackingASTConsumer(std::vector<const Decl *> &TopLevelDecls)
+      : TopLevelDecls(TopLevelDecls) {}
 
-  IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
-      CompilerInstance::createDiagnostics(new DiagnosticOptions);
+  bool HandleTopLevelDecl(DeclGroupRef DG) override {
+    for (const Decl *D : DG) {
+      // ObjCMethodDecl are not actually top-level decls.
+      if (isa<ObjCMethodDecl>(D))
+        continue;
 
-  std::vector<const char *> ArgStrs;
-  for (const auto &S : Commands.front().CommandLine)
-    ArgStrs.push_back(S.c_str());
+      TopLevelDecls.push_back(D);
+    }
+    return true;
+  }
 
-  ASTUnit::RemappedFile RemappedSource(
-      FileName,
-      llvm::MemoryBuffer::getMemBufferCopy(Contents, FileName).release());
+private:
+  std::vector<const Decl *> &TopLevelDecls;
+};
 
-  auto ArgP = &*ArgStrs.begin();
-  Unit = std::unique_ptr<ASTUnit>(ASTUnit::LoadFromCommandLine(
-      ArgP, ArgP + ArgStrs.size(), PCHs, Diags, ResourceDir,
-      /*OnlyLocalDecls=*/false, /*CaptureDiagnostics=*/true, RemappedSource,
-      /*RemappedFilesKeepOriginalName=*/true,
-      /*PrecompilePreambleAfterNParses=*/1, /*TUKind=*/TU_Prefix,
-      /*CacheCodeCompletionResults=*/true,
-      /*IncludeBriefCommentsInCodeCompletion=*/true,
-      /*AllowPCHWithCompilerErrors=*/true,
-      /*SkipFunctionBodies=*/false,
-      /*SingleFileParse=*/false,
-      /*UserFilesAreVolatile=*/false, /*ForSerialization=*/false,
-      /*ModuleFormat=*/llvm::None,
-      /*ErrAST=*/nullptr, VFS));
-  assert(Unit && "Unit wasn't created");
+class ClangdFrontendAction : public SyntaxOnlyAction {
+public:
+  std::vector<const Decl *> takeTopLevelDecls() {
+    return std::move(TopLevelDecls);
+  }
+
+protected:
+  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+                                                 StringRef InFile) override {
+    return llvm::make_unique<DeclTrackingASTConsumer>(/*ref*/ TopLevelDecls);
+  }
+
+private:
+  std::vector<const Decl *> TopLevelDecls;
+};
+
+class CppFilePreambleCallbacks : public PreambleCallbacks {
+public:
+  std::vector<serialization::DeclID> takeTopLevelDeclIDs() {
+    return std::move(TopLevelDeclIDs);
+  }
+
+  void AfterPCHEmitted(ASTWriter &Writer) override {
+    TopLevelDeclIDs.reserve(TopLevelDecls.size());
+    for (Decl *D : TopLevelDecls) {
+      // Invalid top-level decls may not have been serialized.
+      if (D->isInvalidDecl())
+        continue;
+      TopLevelDeclIDs.push_back(Writer.getDeclID(D));
+    }
+  }
+
+  void HandleTopLevelDecl(DeclGroupRef DG) override {
+    for (Decl *D : DG) {
+      if (isa<ObjCMethodDecl>(D))
+        continue;
+      TopLevelDecls.push_back(D);
+    }
+  }
+
+private:
+  std::vector<Decl *> TopLevelDecls;
+  std::vector<serialization::DeclID> TopLevelDeclIDs;
+};
+
+/// Convert from clang diagnostic level to LSP severity.
+static int getSeverity(DiagnosticsEngine::Level L) {
+  switch (L) {
+  case DiagnosticsEngine::Remark:
+    return 4;
+  case DiagnosticsEngine::Note:
+    return 3;
+  case DiagnosticsEngine::Warning:
+    return 2;
+  case DiagnosticsEngine::Fatal:
+  case DiagnosticsEngine::Error:
+    return 1;
+  case DiagnosticsEngine::Ignored:
+    return 0;
+  }
+  llvm_unreachable("Unknown diagnostic level!");
 }
 
-void ClangdUnit::reparse(StringRef Contents,
+/// Get the optional chunk as a string. This function is possibly recursive.
+///
+/// The parameter info for each parameter is appended to the Parameters.
+std::string
+getOptionalParameters(const CodeCompletionString &CCS,
+                      std::vector<ParameterInformation> &Parameters) {
+  std::string Result;
+  for (const auto &Chunk : CCS) {
+    switch (Chunk.Kind) {
+    case CodeCompletionString::CK_Optional:
+      assert(Chunk.Optional &&
+             "Expected the optional code completion string to be non-null.");
+      Result += getOptionalParameters(*Chunk.Optional, Parameters);
+      break;
+    case CodeCompletionString::CK_VerticalSpace:
+      break;
+    case CodeCompletionString::CK_Placeholder:
+      // A string that acts as a placeholder for, e.g., a function call
+      // argument.
+      // Intentional fallthrough here.
+    case CodeCompletionString::CK_CurrentParameter: {
+      // A piece of text that describes the parameter that corresponds to
+      // the code-completion location within a function call, message send,
+      // macro invocation, etc.
+      Result += Chunk.Text;
+      ParameterInformation Info;
+      Info.label = Chunk.Text;
+      Parameters.push_back(std::move(Info));
+      break;
+    }
+    default:
+      Result += Chunk.Text;
+      break;
+    }
+  }
+  return Result;
+}
+
+llvm::Optional<DiagWithFixIts> toClangdDiag(StoredDiagnostic D) {
+  auto Location = D.getLocation();
+  if (!Location.isValid() || !Location.getManager().isInMainFile(Location))
+    return llvm::None;
+
+  Position P;
+  P.line = Location.getSpellingLineNumber() - 1;
+  P.character = Location.getSpellingColumnNumber();
+  Range R = {P, P};
+  clangd::Diagnostic Diag = {R, getSeverity(D.getLevel()), D.getMessage()};
+
+  llvm::SmallVector<tooling::Replacement, 1> FixItsForDiagnostic;
+  for (const FixItHint &Fix : D.getFixIts()) {
+    FixItsForDiagnostic.push_back(clang::tooling::Replacement(
+        Location.getManager(), Fix.RemoveRange, Fix.CodeToInsert));
+  }
+  return DiagWithFixIts{Diag, std::move(FixItsForDiagnostic)};
+}
+
+class StoreDiagsConsumer : public DiagnosticConsumer {
+public:
+  StoreDiagsConsumer(std::vector<DiagWithFixIts> &Output) : Output(Output) {}
+
+  void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+                        const clang::Diagnostic &Info) override {
+    DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);
+
+    if (auto convertedDiag = toClangdDiag(StoredDiagnostic(DiagLevel, Info)))
+      Output.push_back(std::move(*convertedDiag));
+  }
+
+private:
+  std::vector<DiagWithFixIts> &Output;
+};
+
+class EmptyDiagsConsumer : public DiagnosticConsumer {
+public:
+  void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+                        const clang::Diagnostic &Info) override {}
+};
+
+std::unique_ptr<CompilerInvocation>
+createCompilerInvocation(ArrayRef<const char *> ArgList,
+                         IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
                          IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
-  // Do a reparse if this wasn't the first parse.
-  // FIXME: This might have the wrong working directory if it changed in the
-  // meantime.
-  ASTUnit::RemappedFile RemappedSource(
-      FileName,
-      llvm::MemoryBuffer::getMemBufferCopy(Contents, FileName).release());
-
-  Unit->Reparse(PCHs, RemappedSource, VFS);
+  auto CI = createInvocationFromCommandLine(ArgList, std::move(Diags),
+                                            std::move(VFS));
+  // We rely on CompilerInstance to manage the resource (i.e. free them on
+  // EndSourceFile), but that won't happen if DisableFree is set to true.
+  // Since createInvocationFromCommandLine sets it to true, we have to override
+  // it.
+  CI->getFrontendOpts().DisableFree = false;
+  return CI;
 }
 
+/// Creates a CompilerInstance from \p CI, with main buffer overriden to \p
+/// Buffer and arguments to read the PCH from \p Preamble, if \p Preamble is not
+/// null. Note that vfs::FileSystem inside returned instance may differ from \p
+/// VFS if additional file remapping were set in command-line arguments.
+/// On some errors, returns null. When non-null value is returned, it's expected
+/// to be consumed by the FrontendAction as it will have a pointer to the \p
+/// Buffer that will only be deleted if BeginSourceFile is called.
+std::unique_ptr<CompilerInstance>
+prepareCompilerInstance(std::unique_ptr<clang::CompilerInvocation> CI,
+                        const PrecompiledPreamble *Preamble,
+                        std::unique_ptr<llvm::MemoryBuffer> Buffer,
+                        std::shared_ptr<PCHContainerOperations> PCHs,
+                        IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+                        DiagnosticConsumer &DiagsClient) {
+  assert(VFS && "VFS is null");
+  assert(!CI->getPreprocessorOpts().RetainRemappedFileBuffers &&
+         "Setting RetainRemappedFileBuffers to true will cause a memory leak "
+         "of ContentsBuffer");
+
+  // NOTE: we use Buffer.get() when adding remapped files, so we have to make
+  // sure it will be released if no error is emitted.
+  if (Preamble) {
+    Preamble->AddImplicitPreamble(*CI, Buffer.get());
+  } else {
+    CI->getPreprocessorOpts().addRemappedFile(
+        CI->getFrontendOpts().Inputs[0].getFile(), Buffer.get());
+  }
+
+  auto Clang = llvm::make_unique<CompilerInstance>(PCHs);
+  Clang->setInvocation(std::move(CI));
+  Clang->createDiagnostics(&DiagsClient, false);
+
+  if (auto VFSWithRemapping = createVFSFromCompilerInvocation(
+          Clang->getInvocation(), Clang->getDiagnostics(), VFS))
+    VFS = VFSWithRemapping;
+  Clang->setVirtualFileSystem(VFS);
+
+  Clang->setTarget(TargetInfo::CreateTargetInfo(
+      Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
+  if (!Clang->hasTarget())
+    return nullptr;
+
+  // RemappedFileBuffers will handle the lifetime of the Buffer pointer,
+  // release it.
+  Buffer.release();
+  return Clang;
+}
+
+template <class T> bool futureIsReady(std::shared_future<T> const &Future) {
+  return Future.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
+}
+
+} // namespace
+
 namespace {
 
 CompletionItemKind getKind(CXCursorKind K) {
@@ -117,14 +311,50 @@
   }
 }
 
-class CompletionItemsCollector : public CodeCompleteConsumer {
-  std::vector<CompletionItem> *Items;
-  std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;
-  CodeCompletionTUInfo CCTUInfo;
+std::string escapeSnippet(const llvm::StringRef Text) {
+  std::string Result;
+  Result.reserve(Text.size()); // Assume '$', '}' and '\\' are rare.
+  for (const auto Character : Text) {
+    if (Character == '$' || Character == '}' || Character == '\\')
+      Result.push_back('\\');
+    Result.push_back(Character);
+  }
+  return Result;
+}
 
+std::string getDocumentation(const CodeCompletionString &CCS) {
+  // Things like __attribute__((nonnull(1,3))) and [[noreturn]]. Present this
+  // information in the documentation field.
+  std::string Result;
+  const unsigned AnnotationCount = CCS.getAnnotationCount();
+  if (AnnotationCount > 0) {
+    Result += "Annotation";
+    if (AnnotationCount == 1) {
+      Result += ": ";
+    } else /* AnnotationCount > 1 */ {
+      Result += "s: ";
+    }
+    for (unsigned I = 0; I < AnnotationCount; ++I) {
+      Result += CCS.getAnnotation(I);
+      Result.push_back(I == AnnotationCount - 1 ? '\n' : ' ');
+    }
+  }
+  // Add brief documentation (if there is any).
+  if (CCS.getBriefComment() != nullptr) {
+    if (!Result.empty()) {
+      // This means we previously added annotations. Add an extra newline
+      // character to make the annotations stand out.
+      Result.push_back('\n');
+    }
+    Result += CCS.getBriefComment();
+  }
+  return Result;
+}
+
+class CompletionItemsCollector : public CodeCompleteConsumer {
 public:
-  CompletionItemsCollector(std::vector<CompletionItem> *Items,
-                           const CodeCompleteOptions &CodeCompleteOpts)
+  CompletionItemsCollector(const CodeCompleteOptions &CodeCompleteOpts,
+                           std::vector<CompletionItem> &Items)
       : CodeCompleteConsumer(CodeCompleteOpts, /*OutputIsBinary=*/false),
         Items(Items),
         Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),
@@ -132,132 +362,1024 @@
 
   void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,
                                   CodeCompletionResult *Results,
-                                  unsigned NumResults) override {
-    for (unsigned I = 0; I != NumResults; ++I) {
-      CodeCompletionResult &Result = Results[I];
-      CodeCompletionString *CCS = Result.CreateCodeCompletionString(
+                                  unsigned NumResults) override final {
+    Items.reserve(NumResults);
+    for (unsigned I = 0; I < NumResults; ++I) {
+      auto &Result = Results[I];
+      const auto *CCS = Result.CreateCodeCompletionString(
           S, Context, *Allocator, CCTUInfo,
           CodeCompleteOpts.IncludeBriefComments);
-      if (CCS) {
-        CompletionItem Item;
-        for (CodeCompletionString::Chunk C : *CCS) {
-          switch (C.Kind) {
-          case CodeCompletionString::CK_ResultType:
-            Item.detail = C.Text;
-            break;
-          case CodeCompletionString::CK_Optional:
-            break;
-          default:
-            Item.label += C.Text;
-            break;
-          }
-        }
-        assert(CCS->getTypedText());
-        Item.kind = getKind(Result.CursorKind);
-        // Priority is a 16-bit integer, hence at most 5 digits.
-        // Since identifiers with higher priority need to come first,
-        // we subtract the priority from 99999.
-        // For example, the sort text of the identifier 'a' with priority 35
-        // is 99964a.
-        assert(CCS->getPriority() < 99999 && "Expecting code completion result "
-                                             "priority to have at most "
-                                             "5-digits");
-        llvm::raw_string_ostream(Item.sortText) << llvm::format(
-            "%05d%s", 99999 - CCS->getPriority(), CCS->getTypedText());
-        Item.insertText = Item.filterText = CCS->getTypedText();
-        if (CCS->getBriefComment())
-          Item.documentation = CCS->getBriefComment();
-        Items->push_back(std::move(Item));
-      }
+      assert(CCS && "Expected the CodeCompletionString to be non-null");
+      Items.push_back(ProcessCodeCompleteResult(Result, *CCS));
     }
   }
 
   GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; }
 
   CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
-};
+
+private:
+  CompletionItem
+  ProcessCodeCompleteResult(const CodeCompletionResult &Result,
+                            const CodeCompletionString &CCS) const {
+
+    // Adjust this to InsertTextFormat::Snippet iff we encounter a
+    // CK_Placeholder chunk in SnippetCompletionItemsCollector.
+    CompletionItem Item;
+    Item.insertTextFormat = InsertTextFormat::PlainText;
+
+    Item.documentation = getDocumentation(CCS);
+
+    // Fill in the label, detail, insertText and filterText fields of the
+    // CompletionItem.
+    ProcessChunks(CCS, Item);
+
+    // Fill in the kind field of the CompletionItem.
+    Item.kind = getKind(Result.CursorKind);
+
+    FillSortText(CCS, Item);
+
+    return Item;
+  }
+
+  virtual void ProcessChunks(const CodeCompletionString &CCS,
+                             CompletionItem &Item) const = 0;
+
+  static int GetSortPriority(const CodeCompletionString &CCS) {
+    int Score = CCS.getPriority();
+    // Fill in the sortText of the CompletionItem.
+    assert(Score <= 99999 && "Expecting code completion result "
+                             "priority to have at most 5-digits");
+
+    const int Penalty = 100000;
+    switch (static_cast<CXAvailabilityKind>(CCS.getAvailability())) {
+    case CXAvailability_Available:
+      // No penalty.
+      break;
+    case CXAvailability_Deprecated:
+      Score += Penalty;
+      break;
+    case CXAvailability_NotAccessible:
+      Score += 2 * Penalty;
+      break;
+    case CXAvailability_NotAvailable:
+      Score += 3 * Penalty;
+      break;
+    }
+
+    return Score;
+  }
+
+  static void FillSortText(const CodeCompletionString &CCS,
+                           CompletionItem &Item) {
+    int Priority = GetSortPriority(CCS);
+    // Fill in the sortText of the CompletionItem.
+    assert(Priority <= 999999 &&
+           "Expecting sort priority to have at most 6-digits");
+    llvm::raw_string_ostream(Item.sortText)
+        << llvm::format("%06d%s", Priority, Item.filterText.c_str());
+  }
+
+  std::vector<CompletionItem> &Items;
+  std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;
+  CodeCompletionTUInfo CCTUInfo;
+
+}; // CompletionItemsCollector
+
+bool isInformativeQualifierChunk(CodeCompletionString::Chunk const &Chunk) {
+  return Chunk.Kind == CodeCompletionString::CK_Informative &&
+         StringRef(Chunk.Text).endswith("::");
+}
+
+class PlainTextCompletionItemsCollector final
+    : public CompletionItemsCollector {
+
+public:
+  PlainTextCompletionItemsCollector(const CodeCompleteOptions &CodeCompleteOpts,
+                                    std::vector<CompletionItem> &Items)
+      : CompletionItemsCollector(CodeCompleteOpts, Items) {}
+
+private:
+  void ProcessChunks(const CodeCompletionString &CCS,
+                     CompletionItem &Item) const override {
+    for (const auto &Chunk : CCS) {
+      // Informative qualifier chunks only clutter completion results, skip
+      // them.
+      if (isInformativeQualifierChunk(Chunk))
+        continue;
+
+      switch (Chunk.Kind) {
+      case CodeCompletionString::CK_TypedText:
+        // There's always exactly one CK_TypedText chunk.
+        Item.insertText = Item.filterText = Chunk.Text;
+        Item.label += Chunk.Text;
+        break;
+      case CodeCompletionString::CK_ResultType:
+        assert(Item.detail.empty() && "Unexpected extraneous CK_ResultType");
+        Item.detail = Chunk.Text;
+        break;
+      case CodeCompletionString::CK_Optional:
+        break;
+      default:
+        Item.label += Chunk.Text;
+        break;
+      }
+    }
+  }
+}; // PlainTextCompletionItemsCollector
+
+class SnippetCompletionItemsCollector final : public CompletionItemsCollector {
+
+public:
+  SnippetCompletionItemsCollector(const CodeCompleteOptions &CodeCompleteOpts,
+                                  std::vector<CompletionItem> &Items)
+      : CompletionItemsCollector(CodeCompleteOpts, Items) {}
+
+private:
+  void ProcessChunks(const CodeCompletionString &CCS,
+                     CompletionItem &Item) const override {
+    unsigned ArgCount = 0;
+    for (const auto &Chunk : CCS) {
+      // Informative qualifier chunks only clutter completion results, skip
+      // them.
+      if (isInformativeQualifierChunk(Chunk))
+        continue;
+
+      switch (Chunk.Kind) {
+      case CodeCompletionString::CK_TypedText:
+        // The piece of text that the user is expected to type to match
+        // the code-completion string, typically a keyword or the name of
+        // a declarator or macro.
+        Item.filterText = Chunk.Text;
+        // Note intentional fallthrough here.
+      case CodeCompletionString::CK_Text:
+        // A piece of text that should be placed in the buffer,
+        // e.g., parentheses or a comma in a function call.
+        Item.label += Chunk.Text;
+        Item.insertText += Chunk.Text;
+        break;
+      case CodeCompletionString::CK_Optional:
+        // A code completion string that is entirely optional.
+        // For example, an optional code completion string that
+        // describes the default arguments in a function call.
+
+        // FIXME: Maybe add an option to allow presenting the optional chunks?
+        break;
+      case CodeCompletionString::CK_Placeholder:
+        // A string that acts as a placeholder for, e.g., a function call
+        // argument.
+        ++ArgCount;
+        Item.insertText += "${" + std::to_string(ArgCount) + ':' +
+                           escapeSnippet(Chunk.Text) + '}';
+        Item.label += Chunk.Text;
+        Item.insertTextFormat = InsertTextFormat::Snippet;
+        break;
+      case CodeCompletionString::CK_Informative:
+        // A piece of text that describes something about the result
+        // but should not be inserted into the buffer.
+        // For example, the word "const" for a const method, or the name of
+        // the base class for methods that are part of the base class.
+        Item.label += Chunk.Text;
+        // Don't put the informative chunks in the insertText.
+        break;
+      case CodeCompletionString::CK_ResultType:
+        // A piece of text that describes the type of an entity or,
+        // for functions and methods, the return type.
+        assert(Item.detail.empty() && "Unexpected extraneous CK_ResultType");
+        Item.detail = Chunk.Text;
+        break;
+      case CodeCompletionString::CK_CurrentParameter:
+        // A piece of text that describes the parameter that corresponds to
+        // the code-completion location within a function call, message send,
+        // macro invocation, etc.
+        //
+        // This should never be present while collecting completion items,
+        // only while collecting overload candidates.
+        llvm_unreachable("Unexpected CK_CurrentParameter while collecting "
+                         "CompletionItems");
+        break;
+      case CodeCompletionString::CK_LeftParen:
+        // A left parenthesis ('(').
+      case CodeCompletionString::CK_RightParen:
+        // A right parenthesis (')').
+      case CodeCompletionString::CK_LeftBracket:
+        // A left bracket ('[').
+      case CodeCompletionString::CK_RightBracket:
+        // A right bracket (']').
+      case CodeCompletionString::CK_LeftBrace:
+        // A left brace ('{').
+      case CodeCompletionString::CK_RightBrace:
+        // A right brace ('}').
+      case CodeCompletionString::CK_LeftAngle:
+        // A left angle bracket ('<').
+      case CodeCompletionString::CK_RightAngle:
+        // A right angle bracket ('>').
+      case CodeCompletionString::CK_Comma:
+        // A comma separator (',').
+      case CodeCompletionString::CK_Colon:
+        // A colon (':').
+      case CodeCompletionString::CK_SemiColon:
+        // A semicolon (';').
+      case CodeCompletionString::CK_Equal:
+        // An '=' sign.
+      case CodeCompletionString::CK_HorizontalSpace:
+        // Horizontal whitespace (' ').
+        Item.insertText += Chunk.Text;
+        Item.label += Chunk.Text;
+        break;
+      case CodeCompletionString::CK_VerticalSpace:
+        // Vertical whitespace ('\n' or '\r\n', depending on the
+        // platform).
+        Item.insertText += Chunk.Text;
+        // Don't even add a space to the label.
+        break;
+      }
+    }
+  }
+}; // SnippetCompletionItemsCollector
+
+class SignatureHelpCollector final : public CodeCompleteConsumer {
+
+public:
+  SignatureHelpCollector(const CodeCompleteOptions &CodeCompleteOpts,
+                         SignatureHelp &SigHelp)
+      : CodeCompleteConsumer(CodeCompleteOpts, /*OutputIsBinary=*/false),
+        SigHelp(SigHelp),
+        Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),
+        CCTUInfo(Allocator) {}
+
+  void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
+                                 OverloadCandidate *Candidates,
+                                 unsigned NumCandidates) override {
+    SigHelp.signatures.reserve(NumCandidates);
+    // FIXME(rwols): How can we determine the "active overload candidate"?
+    // Right now the overloaded candidates seem to be provided in a "best fit"
+    // order, so I'm not too worried about this.
+    SigHelp.activeSignature = 0;
+    assert(CurrentArg <= (unsigned)std::numeric_limits<int>::max() &&
+           "too many arguments");
+    SigHelp.activeParameter = static_cast<int>(CurrentArg);
+    for (unsigned I = 0; I < NumCandidates; ++I) {
+      const auto &Candidate = Candidates[I];
+      const auto *CCS = Candidate.CreateSignatureString(
+          CurrentArg, S, *Allocator, CCTUInfo, true);
+      assert(CCS && "Expected the CodeCompletionString to be non-null");
+      SigHelp.signatures.push_back(ProcessOverloadCandidate(Candidate, *CCS));
+    }
+  }
+
+  GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; }
+
+  CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
+
+private:
+  SignatureInformation
+  ProcessOverloadCandidate(const OverloadCandidate &Candidate,
+                           const CodeCompletionString &CCS) const {
+    SignatureInformation Result;
+    const char *ReturnType = nullptr;
+
+    Result.documentation = getDocumentation(CCS);
+
+    for (const auto &Chunk : CCS) {
+      switch (Chunk.Kind) {
+      case CodeCompletionString::CK_ResultType:
+        // A piece of text that describes the type of an entity or,
+        // for functions and methods, the return type.
+        assert(!ReturnType && "Unexpected CK_ResultType");
+        ReturnType = Chunk.Text;
+        break;
+      case CodeCompletionString::CK_Placeholder:
+        // A string that acts as a placeholder for, e.g., a function call
+        // argument.
+        // Intentional fallthrough here.
+      case CodeCompletionString::CK_CurrentParameter: {
+        // A piece of text that describes the parameter that corresponds to
+        // the code-completion location within a function call, message send,
+        // macro invocation, etc.
+        Result.label += Chunk.Text;
+        ParameterInformation Info;
+        Info.label = Chunk.Text;
+        Result.parameters.push_back(std::move(Info));
+        break;
+      }
+      case CodeCompletionString::CK_Optional: {
+        // The rest of the parameters are defaulted/optional.
+        assert(Chunk.Optional &&
+               "Expected the optional code completion string to be non-null.");
+        Result.label +=
+            getOptionalParameters(*Chunk.Optional, Result.parameters);
+        break;
+      }
+      case CodeCompletionString::CK_VerticalSpace:
+        break;
+      default:
+        Result.label += Chunk.Text;
+        break;
+      }
+    }
+    if (ReturnType) {
+      Result.label += " -> ";
+      Result.label += ReturnType;
+    }
+    return Result;
+  }
+
+  SignatureHelp &SigHelp;
+  std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;
+  CodeCompletionTUInfo CCTUInfo;
+
+}; // SignatureHelpCollector
+
+bool invokeCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
+                        const CodeCompleteOptions &Options, PathRef FileName,
+                        const tooling::CompileCommand &Command,
+                        PrecompiledPreamble const *Preamble, StringRef Contents,
+                        Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+                        std::shared_ptr<PCHContainerOperations> PCHs,
+                        clangd::Logger &Logger) {
+  std::vector<const char *> ArgStrs;
+  for (const auto &S : Command.CommandLine)
+    ArgStrs.push_back(S.c_str());
+
+  VFS->setCurrentWorkingDirectory(Command.Directory);
+
+  std::unique_ptr<CompilerInvocation> CI;
+  EmptyDiagsConsumer DummyDiagsConsumer;
+  {
+    IntrusiveRefCntPtr<DiagnosticsEngine> CommandLineDiagsEngine =
+        CompilerInstance::createDiagnostics(new DiagnosticOptions,
+                                            &DummyDiagsConsumer, false);
+    CI = createCompilerInvocation(ArgStrs, CommandLineDiagsEngine, VFS);
+  }
+  assert(CI && "Couldn't create CompilerInvocation");
+
+  std::unique_ptr<llvm::MemoryBuffer> ContentsBuffer =
+      llvm::MemoryBuffer::getMemBufferCopy(Contents, FileName);
+
+  // Attempt to reuse the PCH from precompiled preamble, if it was built.
+  if (Preamble) {
+    auto Bounds =
+        ComputePreambleBounds(*CI->getLangOpts(), ContentsBuffer.get(), 0);
+    if (!Preamble->CanReuse(*CI, ContentsBuffer.get(), Bounds, VFS.get()))
+      Preamble = nullptr;
+  }
+
+  auto Clang = prepareCompilerInstance(std::move(CI), Preamble,
+                                       std::move(ContentsBuffer), PCHs, VFS,
+                                       DummyDiagsConsumer);
+  auto &DiagOpts = Clang->getDiagnosticOpts();
+  DiagOpts.IgnoreWarnings = true;
+
+  auto &FrontendOpts = Clang->getFrontendOpts();
+  FrontendOpts.SkipFunctionBodies = true;
+  FrontendOpts.CodeCompleteOpts = Options;
+  FrontendOpts.CodeCompletionAt.FileName = FileName;
+  FrontendOpts.CodeCompletionAt.Line = Pos.line + 1;
+  FrontendOpts.CodeCompletionAt.Column = Pos.character + 1;
+
+  Clang->setCodeCompletionConsumer(Consumer.release());
+
+  SyntaxOnlyAction Action;
+  if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) {
+    Logger.log("BeginSourceFile() failed when running codeComplete for " +
+               FileName);
+    return false;
+  }
+  if (!Action.Execute()) {
+    Logger.log("Execute() failed when running codeComplete for " + FileName);
+    return false;
+  }
+
+  Action.EndSourceFile();
+
+  return true;
+}
+
 } // namespace
 
 std::vector<CompletionItem>
-ClangdUnit::codeComplete(StringRef Contents, Position Pos,
-                         IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
-  CodeCompleteOptions CCO;
-  CCO.IncludeBriefComments = 1;
-  // This is where code completion stores dirty buffers. Need to free after
-  // completion.
-  SmallVector<const llvm::MemoryBuffer *, 4> OwnedBuffers;
-  SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
-  IntrusiveRefCntPtr<DiagnosticsEngine> DiagEngine(
-      new DiagnosticsEngine(new DiagnosticIDs, new DiagnosticOptions));
-  std::vector<CompletionItem> Items;
-  CompletionItemsCollector Collector(&Items, CCO);
-
-  ASTUnit::RemappedFile RemappedSource(
-      FileName,
-      llvm::MemoryBuffer::getMemBufferCopy(Contents, FileName).release());
-
-  IntrusiveRefCntPtr<FileManager> FileMgr(
-      new FileManager(Unit->getFileSystemOpts(), VFS));
-  IntrusiveRefCntPtr<SourceManager> SourceMgr(
-      new SourceManager(*DiagEngine, *FileMgr));
-  // CodeComplete seems to require fresh LangOptions.
-  LangOptions LangOpts = Unit->getLangOpts();
-  // The language server protocol uses zero-based line and column numbers.
-  // The clang code completion uses one-based numbers.
-  Unit->CodeComplete(FileName, Pos.line + 1, Pos.character + 1, RemappedSource,
-                     CCO.IncludeMacros, CCO.IncludeCodePatterns,
-                     CCO.IncludeBriefComments, Collector, PCHs, *DiagEngine,
-                     LangOpts, *SourceMgr, *FileMgr, StoredDiagnostics,
-                     OwnedBuffers);
-  for (const llvm::MemoryBuffer *Buffer : OwnedBuffers)
-    delete Buffer;
-  return Items;
+clangd::codeComplete(PathRef FileName, tooling::CompileCommand Command,
+                     PrecompiledPreamble const *Preamble, StringRef Contents,
+                     Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+                     std::shared_ptr<PCHContainerOperations> PCHs,
+                     bool SnippetCompletions, clangd::Logger &Logger) {
+  std::vector<CompletionItem> Results;
+  CodeCompleteOptions Options;
+  std::unique_ptr<CodeCompleteConsumer> Consumer;
+  Options.IncludeGlobals = true;
+  Options.IncludeMacros = true;
+  Options.IncludeBriefComments = true;
+  if (SnippetCompletions) {
+    Options.IncludeCodePatterns = true;
+    Consumer =
+        llvm::make_unique<SnippetCompletionItemsCollector>(Options, Results);
+  } else {
+    Options.IncludeCodePatterns = false;
+    Consumer =
+        llvm::make_unique<PlainTextCompletionItemsCollector>(Options, Results);
+  }
+  invokeCodeComplete(std::move(Consumer), Options, FileName, Command, Preamble,
+                     Contents, Pos, std::move(VFS), std::move(PCHs), Logger);
+  return Results;
 }
 
-namespace {
-/// Convert from clang diagnostic level to LSP severity.
-static int getSeverity(DiagnosticsEngine::Level L) {
-  switch (L) {
-  case DiagnosticsEngine::Remark:
-    return 4;
-  case DiagnosticsEngine::Note:
-    return 3;
-  case DiagnosticsEngine::Warning:
-    return 2;
-  case DiagnosticsEngine::Fatal:
-  case DiagnosticsEngine::Error:
-    return 1;
-  case DiagnosticsEngine::Ignored:
-    return 0;
-  }
-  llvm_unreachable("Unknown diagnostic level!");
-}
-} // namespace
-
-std::vector<DiagWithFixIts> ClangdUnit::getLocalDiagnostics() const {
-  std::vector<DiagWithFixIts> Result;
-  for (ASTUnit::stored_diag_iterator D = Unit->stored_diag_begin(),
-                                     DEnd = Unit->stored_diag_end();
-       D != DEnd; ++D) {
-    if (!D->getLocation().isValid() ||
-        !D->getLocation().getManager().isInMainFile(D->getLocation()))
-      continue;
-    Position P;
-    P.line = D->getLocation().getSpellingLineNumber() - 1;
-    P.character = D->getLocation().getSpellingColumnNumber();
-    Range R = {P, P};
-    clangd::Diagnostic Diag = {R, getSeverity(D->getLevel()), D->getMessage()};
-
-    llvm::SmallVector<tooling::Replacement, 1> FixItsForDiagnostic;
-    for (const FixItHint &Fix : D->getFixIts()) {
-      FixItsForDiagnostic.push_back(clang::tooling::Replacement(
-          Unit->getSourceManager(), Fix.RemoveRange, Fix.CodeToInsert));
-    }
-    Result.push_back({Diag, std::move(FixItsForDiagnostic)});
-  }
+SignatureHelp
+clangd::signatureHelp(PathRef FileName, tooling::CompileCommand Command,
+                      PrecompiledPreamble const *Preamble, StringRef Contents,
+                      Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+                      std::shared_ptr<PCHContainerOperations> PCHs,
+                      clangd::Logger &Logger) {
+  SignatureHelp Result;
+  CodeCompleteOptions Options;
+  Options.IncludeGlobals = false;
+  Options.IncludeMacros = false;
+  Options.IncludeCodePatterns = false;
+  Options.IncludeBriefComments = true;
+  invokeCodeComplete(llvm::make_unique<SignatureHelpCollector>(Options, Result),
+                     Options, FileName, Command, Preamble, Contents, Pos,
+                     std::move(VFS), std::move(PCHs), Logger);
   return Result;
 }
 
-void ClangdUnit::dumpAST(llvm::raw_ostream &OS) const {
-  Unit->getASTContext().getTranslationUnitDecl()->dump(OS, true);
+void clangd::dumpAST(ParsedAST &AST, llvm::raw_ostream &OS) {
+  AST.getASTContext().getTranslationUnitDecl()->dump(OS, true);
+}
+
+llvm::Optional<ParsedAST>
+ParsedAST::Build(std::unique_ptr<clang::CompilerInvocation> CI,
+                 const PrecompiledPreamble *Preamble,
+                 ArrayRef<serialization::DeclID> PreambleDeclIDs,
+                 std::unique_ptr<llvm::MemoryBuffer> Buffer,
+                 std::shared_ptr<PCHContainerOperations> PCHs,
+                 IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+                 clangd::Logger &Logger) {
+
+  std::vector<DiagWithFixIts> ASTDiags;
+  StoreDiagsConsumer UnitDiagsConsumer(/*ref*/ ASTDiags);
+
+  auto Clang =
+      prepareCompilerInstance(std::move(CI), Preamble, std::move(Buffer), PCHs,
+                              VFS, /*ref*/ UnitDiagsConsumer);
+
+  // Recover resources if we crash before exiting this method.
+  llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance> CICleanup(
+      Clang.get());
+
+  auto Action = llvm::make_unique<ClangdFrontendAction>();
+  const FrontendInputFile &MainInput = Clang->getFrontendOpts().Inputs[0];
+  if (!Action->BeginSourceFile(*Clang, MainInput)) {
+    Logger.log("BeginSourceFile() failed when building AST for " +
+               MainInput.getFile());
+    return llvm::None;
+  }
+  if (!Action->Execute())
+    Logger.log("Execute() failed when building AST for " + MainInput.getFile());
+
+  // UnitDiagsConsumer is local, we can not store it in CompilerInstance that
+  // has a longer lifetime.
+  Clang->getDiagnostics().setClient(new EmptyDiagsConsumer);
+
+  std::vector<const Decl *> ParsedDecls = Action->takeTopLevelDecls();
+  std::vector<serialization::DeclID> PendingDecls;
+  if (Preamble) {
+    PendingDecls.reserve(PreambleDeclIDs.size());
+    PendingDecls.insert(PendingDecls.begin(), PreambleDeclIDs.begin(),
+                        PreambleDeclIDs.end());
+  }
+
+  return ParsedAST(std::move(Clang), std::move(Action), std::move(ParsedDecls),
+                   std::move(PendingDecls), std::move(ASTDiags));
+}
+
+namespace {
+
+SourceLocation getMacroArgExpandedLocation(const SourceManager &Mgr,
+                                           const FileEntry *FE,
+                                           unsigned Offset) {
+  SourceLocation FileLoc = Mgr.translateFileLineCol(FE, 1, 1);
+  return Mgr.getMacroArgExpandedLocation(FileLoc.getLocWithOffset(Offset));
+}
+
+SourceLocation getMacroArgExpandedLocation(const SourceManager &Mgr,
+                                           const FileEntry *FE, Position Pos) {
+  SourceLocation InputLoc =
+      Mgr.translateFileLineCol(FE, Pos.line + 1, Pos.character + 1);
+  return Mgr.getMacroArgExpandedLocation(InputLoc);
+}
+
+/// Finds declarations locations that a given source location refers to.
+class DeclarationLocationsFinder : public index::IndexDataConsumer {
+  std::vector<Location> DeclarationLocations;
+  const SourceLocation &SearchedLocation;
+  const ASTContext &AST;
+  Preprocessor &PP;
+
+public:
+  DeclarationLocationsFinder(raw_ostream &OS,
+                             const SourceLocation &SearchedLocation,
+                             ASTContext &AST, Preprocessor &PP)
+      : SearchedLocation(SearchedLocation), AST(AST), PP(PP) {}
+
+  std::vector<Location> takeLocations() {
+    // Don't keep the same location multiple times.
+    // This can happen when nodes in the AST are visited twice.
+    std::sort(DeclarationLocations.begin(), DeclarationLocations.end());
+    auto last =
+        std::unique(DeclarationLocations.begin(), DeclarationLocations.end());
+    DeclarationLocations.erase(last, DeclarationLocations.end());
+    return std::move(DeclarationLocations);
+  }
+
+  bool
+  handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
+                      ArrayRef<index::SymbolRelation> Relations, FileID FID,
+                      unsigned Offset,
+                      index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
+    if (isSearchedLocation(FID, Offset)) {
+      addDeclarationLocation(D->getSourceRange());
+    }
+    return true;
+  }
+
+private:
+  bool isSearchedLocation(FileID FID, unsigned Offset) const {
+    const SourceManager &SourceMgr = AST.getSourceManager();
+    return SourceMgr.getFileOffset(SearchedLocation) == Offset &&
+           SourceMgr.getFileID(SearchedLocation) == FID;
+  }
+
+  void addDeclarationLocation(const SourceRange &ValSourceRange) {
+    const SourceManager &SourceMgr = AST.getSourceManager();
+    const LangOptions &LangOpts = AST.getLangOpts();
+    SourceLocation LocStart = ValSourceRange.getBegin();
+    SourceLocation LocEnd = Lexer::getLocForEndOfToken(ValSourceRange.getEnd(),
+                                                       0, SourceMgr, LangOpts);
+    Position Begin;
+    Begin.line = SourceMgr.getSpellingLineNumber(LocStart) - 1;
+    Begin.character = SourceMgr.getSpellingColumnNumber(LocStart) - 1;
+    Position End;
+    End.line = SourceMgr.getSpellingLineNumber(LocEnd) - 1;
+    End.character = SourceMgr.getSpellingColumnNumber(LocEnd) - 1;
+    Range R = {Begin, End};
+    Location L;
+    L.uri = URI::fromFile(
+        SourceMgr.getFilename(SourceMgr.getSpellingLoc(LocStart)));
+    L.range = R;
+    DeclarationLocations.push_back(L);
+  }
+
+  void finish() override {
+    // Also handle possible macro at the searched location.
+    Token Result;
+    if (!Lexer::getRawToken(SearchedLocation, Result, AST.getSourceManager(),
+                            AST.getLangOpts(), false)) {
+      if (Result.is(tok::raw_identifier)) {
+        PP.LookUpIdentifierInfo(Result);
+      }
+      IdentifierInfo *IdentifierInfo = Result.getIdentifierInfo();
+      if (IdentifierInfo && IdentifierInfo->hadMacroDefinition()) {
+        std::pair<FileID, unsigned int> DecLoc =
+            AST.getSourceManager().getDecomposedExpansionLoc(SearchedLocation);
+        // Get the definition just before the searched location so that a macro
+        // referenced in a '#undef MACRO' can still be found.
+        SourceLocation BeforeSearchedLocation = getMacroArgExpandedLocation(
+            AST.getSourceManager(),
+            AST.getSourceManager().getFileEntryForID(DecLoc.first),
+            DecLoc.second - 1);
+        MacroDefinition MacroDef =
+            PP.getMacroDefinitionAtLoc(IdentifierInfo, BeforeSearchedLocation);
+        MacroInfo *MacroInf = MacroDef.getMacroInfo();
+        if (MacroInf) {
+          addDeclarationLocation(SourceRange(MacroInf->getDefinitionLoc(),
+                                             MacroInf->getDefinitionEndLoc()));
+        }
+      }
+    }
+  }
+};
+
+SourceLocation getBeginningOfIdentifier(ParsedAST &Unit, const Position &Pos,
+                                        const FileEntry *FE) {
+  // The language server protocol uses zero-based line and column numbers.
+  // Clang uses one-based numbers.
+
+  const ASTContext &AST = Unit.getASTContext();
+  const SourceManager &SourceMgr = AST.getSourceManager();
+
+  SourceLocation InputLocation =
+      getMacroArgExpandedLocation(SourceMgr, FE, Pos);
+  if (Pos.character == 0) {
+    return InputLocation;
+  }
+
+  // This handle cases where the position is in the middle of a token or right
+  // after the end of a token. In theory we could just use GetBeginningOfToken
+  // to find the start of the token at the input position, but this doesn't
+  // work when right after the end, i.e. foo|.
+  // So try to go back by one and see if we're still inside the an identifier
+  // token. If so, Take the beginning of this token.
+  // (It should be the same identifier because you can't have two adjacent
+  // identifiers without another token in between.)
+  SourceLocation PeekBeforeLocation = getMacroArgExpandedLocation(
+      SourceMgr, FE, Position{Pos.line, Pos.character - 1});
+  Token Result;
+  if (Lexer::getRawToken(PeekBeforeLocation, Result, SourceMgr,
+                         AST.getLangOpts(), false)) {
+    // getRawToken failed, just use InputLocation.
+    return InputLocation;
+  }
+
+  if (Result.is(tok::raw_identifier)) {
+    return Lexer::GetBeginningOfToken(PeekBeforeLocation, SourceMgr,
+                                      AST.getLangOpts());
+  }
+
+  return InputLocation;
+}
+} // namespace
+
+std::vector<Location> clangd::findDefinitions(ParsedAST &AST, Position Pos,
+                                              clangd::Logger &Logger) {
+  const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
+  const FileEntry *FE = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
+  if (!FE)
+    return {};
+
+  SourceLocation SourceLocationBeg = getBeginningOfIdentifier(AST, Pos, FE);
+
+  auto DeclLocationsFinder = std::make_shared<DeclarationLocationsFinder>(
+      llvm::errs(), SourceLocationBeg, AST.getASTContext(),
+      AST.getPreprocessor());
+  index::IndexingOptions IndexOpts;
+  IndexOpts.SystemSymbolFilter =
+      index::IndexingOptions::SystemSymbolFilterKind::All;
+  IndexOpts.IndexFunctionLocals = true;
+
+  indexTopLevelDecls(AST.getASTContext(), AST.getTopLevelDecls(),
+                     DeclLocationsFinder, IndexOpts);
+
+  return DeclLocationsFinder->takeLocations();
+}
+
+void ParsedAST::ensurePreambleDeclsDeserialized() {
+  if (PendingTopLevelDecls.empty())
+    return;
+
+  std::vector<const Decl *> Resolved;
+  Resolved.reserve(PendingTopLevelDecls.size());
+
+  ExternalASTSource &Source = *getASTContext().getExternalSource();
+  for (serialization::DeclID TopLevelDecl : PendingTopLevelDecls) {
+    // Resolve the declaration ID to an actual declaration, possibly
+    // deserializing the declaration in the process.
+    if (Decl *D = Source.GetExternalDecl(TopLevelDecl))
+      Resolved.push_back(D);
+  }
+
+  TopLevelDecls.reserve(TopLevelDecls.size() + PendingTopLevelDecls.size());
+  TopLevelDecls.insert(TopLevelDecls.begin(), Resolved.begin(), Resolved.end());
+
+  PendingTopLevelDecls.clear();
+}
+
+ParsedAST::ParsedAST(ParsedAST &&Other) = default;
+
+ParsedAST &ParsedAST::operator=(ParsedAST &&Other) = default;
+
+ParsedAST::~ParsedAST() {
+  if (Action) {
+    Action->EndSourceFile();
+  }
+}
+
+ASTContext &ParsedAST::getASTContext() { return Clang->getASTContext(); }
+
+const ASTContext &ParsedAST::getASTContext() const {
+  return Clang->getASTContext();
+}
+
+Preprocessor &ParsedAST::getPreprocessor() { return Clang->getPreprocessor(); }
+
+const Preprocessor &ParsedAST::getPreprocessor() const {
+  return Clang->getPreprocessor();
+}
+
+ArrayRef<const Decl *> ParsedAST::getTopLevelDecls() {
+  ensurePreambleDeclsDeserialized();
+  return TopLevelDecls;
+}
+
+const std::vector<DiagWithFixIts> &ParsedAST::getDiagnostics() const {
+  return Diags;
+}
+
+ParsedAST::ParsedAST(std::unique_ptr<CompilerInstance> Clang,
+                     std::unique_ptr<FrontendAction> Action,
+                     std::vector<const Decl *> TopLevelDecls,
+                     std::vector<serialization::DeclID> PendingTopLevelDecls,
+                     std::vector<DiagWithFixIts> Diags)
+    : Clang(std::move(Clang)), Action(std::move(Action)),
+      Diags(std::move(Diags)), TopLevelDecls(std::move(TopLevelDecls)),
+      PendingTopLevelDecls(std::move(PendingTopLevelDecls)) {
+  assert(this->Clang);
+  assert(this->Action);
+}
+
+ParsedASTWrapper::ParsedASTWrapper(ParsedASTWrapper &&Wrapper)
+    : AST(std::move(Wrapper.AST)) {}
+
+ParsedASTWrapper::ParsedASTWrapper(llvm::Optional<ParsedAST> AST)
+    : AST(std::move(AST)) {}
+
+PreambleData::PreambleData(PrecompiledPreamble Preamble,
+                           std::vector<serialization::DeclID> TopLevelDeclIDs,
+                           std::vector<DiagWithFixIts> Diags)
+    : Preamble(std::move(Preamble)),
+      TopLevelDeclIDs(std::move(TopLevelDeclIDs)), Diags(std::move(Diags)) {}
+
+std::shared_ptr<CppFile>
+CppFile::Create(PathRef FileName, tooling::CompileCommand Command,
+                std::shared_ptr<PCHContainerOperations> PCHs,
+                clangd::Logger &Logger) {
+  return std::shared_ptr<CppFile>(
+      new CppFile(FileName, std::move(Command), std::move(PCHs), Logger));
+}
+
+CppFile::CppFile(PathRef FileName, tooling::CompileCommand Command,
+                 std::shared_ptr<PCHContainerOperations> PCHs,
+                 clangd::Logger &Logger)
+    : FileName(FileName), Command(std::move(Command)), RebuildCounter(0),
+      RebuildInProgress(false), PCHs(std::move(PCHs)), Logger(Logger) {
+
+  std::lock_guard<std::mutex> Lock(Mutex);
+  LatestAvailablePreamble = nullptr;
+  PreamblePromise.set_value(nullptr);
+  PreambleFuture = PreamblePromise.get_future();
+
+  ASTPromise.set_value(std::make_shared<ParsedASTWrapper>(llvm::None));
+  ASTFuture = ASTPromise.get_future();
+}
+
+void CppFile::cancelRebuild() { deferCancelRebuild()(); }
+
+UniqueFunction<void()> CppFile::deferCancelRebuild() {
+  std::unique_lock<std::mutex> Lock(Mutex);
+  // Cancel an ongoing rebuild, if any, and wait for it to finish.
+  unsigned RequestRebuildCounter = ++this->RebuildCounter;
+  // Rebuild asserts that futures aren't ready if rebuild is cancelled.
+  // We want to keep this invariant.
+  if (futureIsReady(PreambleFuture)) {
+    PreamblePromise = std::promise<std::shared_ptr<const PreambleData>>();
+    PreambleFuture = PreamblePromise.get_future();
+  }
+  if (futureIsReady(ASTFuture)) {
+    ASTPromise = std::promise<std::shared_ptr<ParsedASTWrapper>>();
+    ASTFuture = ASTPromise.get_future();
+  }
+
+  Lock.unlock();
+  // Notify about changes to RebuildCounter.
+  RebuildCond.notify_all();
+
+  std::shared_ptr<CppFile> That = shared_from_this();
+  return [That, RequestRebuildCounter]() {
+    std::unique_lock<std::mutex> Lock(That->Mutex);
+    CppFile *This = &*That;
+    This->RebuildCond.wait(Lock, [This, RequestRebuildCounter]() {
+      return !This->RebuildInProgress ||
+             This->RebuildCounter != RequestRebuildCounter;
+    });
+
+    // This computation got cancelled itself, do nothing.
+    if (This->RebuildCounter != RequestRebuildCounter)
+      return;
+
+    // Set empty results for Promises.
+    That->PreamblePromise.set_value(nullptr);
+    That->ASTPromise.set_value(std::make_shared<ParsedASTWrapper>(llvm::None));
+  };
+}
+
+llvm::Optional<std::vector<DiagWithFixIts>>
+CppFile::rebuild(StringRef NewContents,
+                 IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
+  return deferRebuild(NewContents, std::move(VFS))();
+}
+
+UniqueFunction<llvm::Optional<std::vector<DiagWithFixIts>>()>
+CppFile::deferRebuild(StringRef NewContents,
+                      IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
+  std::shared_ptr<const PreambleData> OldPreamble;
+  std::shared_ptr<PCHContainerOperations> PCHs;
+  unsigned RequestRebuildCounter;
+  {
+    std::unique_lock<std::mutex> Lock(Mutex);
+    // Increase RebuildCounter to cancel all ongoing FinishRebuild operations.
+    // They will try to exit as early as possible and won't call set_value on
+    // our promises.
+    RequestRebuildCounter = ++this->RebuildCounter;
+    PCHs = this->PCHs;
+
+    // Remember the preamble to be used during rebuild.
+    OldPreamble = this->LatestAvailablePreamble;
+    // Setup std::promises and std::futures for Preamble and AST. Corresponding
+    // futures will wait until the rebuild process is finished.
+    if (futureIsReady(this->PreambleFuture)) {
+      this->PreamblePromise =
+          std::promise<std::shared_ptr<const PreambleData>>();
+      this->PreambleFuture = this->PreamblePromise.get_future();
+    }
+    if (futureIsReady(this->ASTFuture)) {
+      this->ASTPromise = std::promise<std::shared_ptr<ParsedASTWrapper>>();
+      this->ASTFuture = this->ASTPromise.get_future();
+    }
+  } // unlock Mutex.
+  // Notify about changes to RebuildCounter.
+  RebuildCond.notify_all();
+
+  // A helper to function to finish the rebuild. May be run on a different
+  // thread.
+
+  // Don't let this CppFile die before rebuild is finished.
+  std::shared_ptr<CppFile> That = shared_from_this();
+  auto FinishRebuild = [OldPreamble, VFS, RequestRebuildCounter, PCHs,
+                        That](std::string NewContents)
+      -> llvm::Optional<std::vector<DiagWithFixIts>> {
+    // Only one execution of this method is possible at a time.
+    // RebuildGuard will wait for any ongoing rebuilds to finish and will put us
+    // into a state for doing a rebuild.
+    RebuildGuard Rebuild(*That, RequestRebuildCounter);
+    if (Rebuild.wasCancelledBeforeConstruction())
+      return llvm::None;
+
+    std::vector<const char *> ArgStrs;
+    for (const auto &S : That->Command.CommandLine)
+      ArgStrs.push_back(S.c_str());
+
+    VFS->setCurrentWorkingDirectory(That->Command.Directory);
+
+    std::unique_ptr<CompilerInvocation> CI;
+    {
+      // FIXME(ibiryukov): store diagnostics from CommandLine when we start
+      // reporting them.
+      EmptyDiagsConsumer CommandLineDiagsConsumer;
+      IntrusiveRefCntPtr<DiagnosticsEngine> CommandLineDiagsEngine =
+          CompilerInstance::createDiagnostics(new DiagnosticOptions,
+                                              &CommandLineDiagsConsumer, false);
+      CI = createCompilerInvocation(ArgStrs, CommandLineDiagsEngine, VFS);
+    }
+    assert(CI && "Couldn't create CompilerInvocation");
+
+    std::unique_ptr<llvm::MemoryBuffer> ContentsBuffer =
+        llvm::MemoryBuffer::getMemBufferCopy(NewContents, That->FileName);
+
+    // A helper function to rebuild the preamble or reuse the existing one. Does
+    // not mutate any fields, only does the actual computation.
+    auto DoRebuildPreamble = [&]() -> std::shared_ptr<const PreambleData> {
+      auto Bounds =
+          ComputePreambleBounds(*CI->getLangOpts(), ContentsBuffer.get(), 0);
+      if (OldPreamble && OldPreamble->Preamble.CanReuse(
+                             *CI, ContentsBuffer.get(), Bounds, VFS.get())) {
+        return OldPreamble;
+      }
+
+      std::vector<DiagWithFixIts> PreambleDiags;
+      StoreDiagsConsumer PreambleDiagnosticsConsumer(/*ref*/ PreambleDiags);
+      IntrusiveRefCntPtr<DiagnosticsEngine> PreambleDiagsEngine =
+          CompilerInstance::createDiagnostics(
+              &CI->getDiagnosticOpts(), &PreambleDiagnosticsConsumer, false);
+      CppFilePreambleCallbacks SerializedDeclsCollector;
+      auto BuiltPreamble = PrecompiledPreamble::Build(
+          *CI, ContentsBuffer.get(), Bounds, *PreambleDiagsEngine, VFS, PCHs,
+          SerializedDeclsCollector);
+
+      if (BuiltPreamble) {
+        return std::make_shared<PreambleData>(
+            std::move(*BuiltPreamble),
+            SerializedDeclsCollector.takeTopLevelDeclIDs(),
+            std::move(PreambleDiags));
+      } else {
+        return nullptr;
+      }
+    };
+
+    // Compute updated Preamble.
+    std::shared_ptr<const PreambleData> NewPreamble = DoRebuildPreamble();
+    // Publish the new Preamble.
+    {
+      std::lock_guard<std::mutex> Lock(That->Mutex);
+      // We always set LatestAvailablePreamble to the new value, hoping that it
+      // will still be usable in the further requests.
+      That->LatestAvailablePreamble = NewPreamble;
+      if (RequestRebuildCounter != That->RebuildCounter)
+        return llvm::None; // Our rebuild request was cancelled, do nothing.
+      That->PreamblePromise.set_value(NewPreamble);
+    } // unlock Mutex
+
+    // Prepare the Preamble and supplementary data for rebuilding AST.
+    const PrecompiledPreamble *PreambleForAST = nullptr;
+    ArrayRef<serialization::DeclID> SerializedPreambleDecls = llvm::None;
+    std::vector<DiagWithFixIts> Diagnostics;
+    if (NewPreamble) {
+      PreambleForAST = &NewPreamble->Preamble;
+      SerializedPreambleDecls = NewPreamble->TopLevelDeclIDs;
+      Diagnostics.insert(Diagnostics.begin(), NewPreamble->Diags.begin(),
+                         NewPreamble->Diags.end());
+    }
+
+    // Compute updated AST.
+    llvm::Optional<ParsedAST> NewAST =
+        ParsedAST::Build(std::move(CI), PreambleForAST, SerializedPreambleDecls,
+                         std::move(ContentsBuffer), PCHs, VFS, That->Logger);
+
+    if (NewAST) {
+      Diagnostics.insert(Diagnostics.end(), NewAST->getDiagnostics().begin(),
+                         NewAST->getDiagnostics().end());
+    } else {
+      // Don't report even Preamble diagnostics if we coulnd't build AST.
+      Diagnostics.clear();
+    }
+
+    // Publish the new AST.
+    {
+      std::lock_guard<std::mutex> Lock(That->Mutex);
+      if (RequestRebuildCounter != That->RebuildCounter)
+        return Diagnostics; // Our rebuild request was cancelled, don't set
+                            // ASTPromise.
+
+      That->ASTPromise.set_value(
+          std::make_shared<ParsedASTWrapper>(std::move(NewAST)));
+    } // unlock Mutex
+
+    return Diagnostics;
+  };
+
+  return BindWithForward(FinishRebuild, NewContents.str());
+}
+
+std::shared_future<std::shared_ptr<const PreambleData>>
+CppFile::getPreamble() const {
+  std::lock_guard<std::mutex> Lock(Mutex);
+  return PreambleFuture;
+}
+
+std::shared_ptr<const PreambleData> CppFile::getPossiblyStalePreamble() const {
+  std::lock_guard<std::mutex> Lock(Mutex);
+  return LatestAvailablePreamble;
+}
+
+std::shared_future<std::shared_ptr<ParsedASTWrapper>> CppFile::getAST() const {
+  std::lock_guard<std::mutex> Lock(Mutex);
+  return ASTFuture;
+}
+
+tooling::CompileCommand const &CppFile::getCompileCommand() const {
+  return Command;
+}
+
+CppFile::RebuildGuard::RebuildGuard(CppFile &File,
+                                    unsigned RequestRebuildCounter)
+    : File(File), RequestRebuildCounter(RequestRebuildCounter) {
+  std::unique_lock<std::mutex> Lock(File.Mutex);
+  WasCancelledBeforeConstruction = File.RebuildCounter != RequestRebuildCounter;
+  if (WasCancelledBeforeConstruction)
+    return;
+
+  File.RebuildCond.wait(Lock, [&File, RequestRebuildCounter]() {
+    return !File.RebuildInProgress ||
+           File.RebuildCounter != RequestRebuildCounter;
+  });
+
+  WasCancelledBeforeConstruction = File.RebuildCounter != RequestRebuildCounter;
+  if (WasCancelledBeforeConstruction)
+    return;
+
+  File.RebuildInProgress = true;
+}
+
+bool CppFile::RebuildGuard::wasCancelledBeforeConstruction() const {
+  return WasCancelledBeforeConstruction;
+}
+
+CppFile::RebuildGuard::~RebuildGuard() {
+  if (WasCancelledBeforeConstruction)
+    return;
+
+  std::unique_lock<std::mutex> Lock(File.Mutex);
+  assert(File.RebuildInProgress);
+  File.RebuildInProgress = false;
+
+  if (File.RebuildCounter == RequestRebuildCounter) {
+    // Our rebuild request was successful.
+    assert(futureIsReady(File.ASTFuture));
+    assert(futureIsReady(File.PreambleFuture));
+  } else {
+    // Our rebuild request was cancelled, because further reparse was requested.
+    assert(!futureIsReady(File.ASTFuture));
+    assert(!futureIsReady(File.PreambleFuture));
+  }
+
+  Lock.unlock();
+  File.RebuildCond.notify_all();
 }
diff --git a/clangd/ClangdUnit.h b/clangd/ClangdUnit.h
index a11ca02..ad200c2 100644
--- a/clangd/ClangdUnit.h
+++ b/clangd/ClangdUnit.h
@@ -10,18 +10,24 @@
 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDUNIT_H
 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDUNIT_H
 
+#include "Function.h"
 #include "Path.h"
 #include "Protocol.h"
-#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Frontend/PrecompiledPreamble.h"
+#include "clang/Serialization/ASTBitCodes.h"
+#include "clang/Tooling/CompilationDatabase.h"
 #include "clang/Tooling/Core/Replacement.h"
+#include <atomic>
+#include <future>
 #include <memory>
+#include <mutex>
 
 namespace llvm {
 class raw_ostream;
 }
 
 namespace clang {
-class ASTUnit;
 class PCHContainerOperations;
 
 namespace vfs {
@@ -34,45 +40,241 @@
 
 namespace clangd {
 
+class Logger;
+
 /// A diagnostic with its FixIts.
 struct DiagWithFixIts {
   clangd::Diagnostic Diag;
   llvm::SmallVector<tooling::Replacement, 1> FixIts;
 };
 
-/// Stores parsed C++ AST and provides implementations of all operations clangd
-/// would want to perform on parsed C++ files.
-class ClangdUnit {
+/// Stores and provides access to parsed AST.
+class ParsedAST {
 public:
-  ClangdUnit(PathRef FileName, StringRef Contents,
-             std::shared_ptr<PCHContainerOperations> PCHs,
-             std::vector<tooling::CompileCommand> Commands,
-             IntrusiveRefCntPtr<vfs::FileSystem> VFS);
+  /// Attempts to run Clang and store parsed AST. If \p Preamble is non-null
+  /// it is reused during parsing.
+  static llvm::Optional<ParsedAST>
+  Build(std::unique_ptr<clang::CompilerInvocation> CI,
+        const PrecompiledPreamble *Preamble,
+        ArrayRef<serialization::DeclID> PreambleDeclIDs,
+        std::unique_ptr<llvm::MemoryBuffer> Buffer,
+        std::shared_ptr<PCHContainerOperations> PCHs,
+        IntrusiveRefCntPtr<vfs::FileSystem> VFS, clangd::Logger &Logger);
 
-  /// Reparse with new contents.
-  void reparse(StringRef Contents, IntrusiveRefCntPtr<vfs::FileSystem> VFS);
+  ParsedAST(ParsedAST &&Other);
+  ParsedAST &operator=(ParsedAST &&Other);
 
-  /// Get code completions at a specified \p Line and \p Column in \p File.
-  ///
-  /// This function is thread-safe and returns completion items that own the
-  /// data they contain.
-  std::vector<CompletionItem>
-  codeComplete(StringRef Contents, Position Pos,
-               IntrusiveRefCntPtr<vfs::FileSystem> VFS);
-  /// Returns diagnostics and corresponding FixIts for each diagnostic that are
-  /// located in the current file.
-  std::vector<DiagWithFixIts> getLocalDiagnostics() const;
+  ~ParsedAST();
 
-  /// For testing/debugging purposes. Note that this method deserializes all
-  /// unserialized Decls, so use with care.
-  void dumpAST(llvm::raw_ostream &OS) const;
+  ASTContext &getASTContext();
+  const ASTContext &getASTContext() const;
+
+  Preprocessor &getPreprocessor();
+  const Preprocessor &getPreprocessor() const;
+
+  /// This function returns all top-level decls, including those that come
+  /// from Preamble. Decls, coming from Preamble, have to be deserialized, so
+  /// this call might be expensive.
+  ArrayRef<const Decl *> getTopLevelDecls();
+
+  const std::vector<DiagWithFixIts> &getDiagnostics() const;
 
 private:
-  Path FileName;
-  std::unique_ptr<ASTUnit> Unit;
-  std::shared_ptr<PCHContainerOperations> PCHs;
+  ParsedAST(std::unique_ptr<CompilerInstance> Clang,
+            std::unique_ptr<FrontendAction> Action,
+            std::vector<const Decl *> TopLevelDecls,
+            std::vector<serialization::DeclID> PendingTopLevelDecls,
+            std::vector<DiagWithFixIts> Diags);
+
+private:
+  void ensurePreambleDeclsDeserialized();
+
+  // We store an "incomplete" FrontendAction (i.e. no EndSourceFile was called
+  // on it) and CompilerInstance used to run it. That way we don't have to do
+  // complex memory management of all Clang structures on our own. (They are
+  // stored in CompilerInstance and cleaned up by
+  // FrontendAction.EndSourceFile).
+  std::unique_ptr<CompilerInstance> Clang;
+  std::unique_ptr<FrontendAction> Action;
+
+  // Data, stored after parsing.
+  std::vector<DiagWithFixIts> Diags;
+  std::vector<const Decl *> TopLevelDecls;
+  std::vector<serialization::DeclID> PendingTopLevelDecls;
 };
 
+// Provides thread-safe access to ParsedAST.
+class ParsedASTWrapper {
+public:
+  ParsedASTWrapper(ParsedASTWrapper &&Wrapper);
+  ParsedASTWrapper(llvm::Optional<ParsedAST> AST);
+
+  /// Runs \p F on wrapped ParsedAST under lock. Ensures it is not accessed
+  /// concurrently.
+  template <class Func> void runUnderLock(Func F) const {
+    std::lock_guard<std::mutex> Lock(Mutex);
+    F(AST ? AST.getPointer() : nullptr);
+  }
+
+private:
+  // This wrapper is used as an argument to std::shared_future (and it returns a
+  // const ref in get()), but we need to have non-const ref in order to
+  // implement some features.
+  mutable std::mutex Mutex;
+  mutable llvm::Optional<ParsedAST> AST;
+};
+
+// Stores Preamble and associated data.
+struct PreambleData {
+  PreambleData(PrecompiledPreamble Preamble,
+               std::vector<serialization::DeclID> TopLevelDeclIDs,
+               std::vector<DiagWithFixIts> Diags);
+
+  PrecompiledPreamble Preamble;
+  std::vector<serialization::DeclID> TopLevelDeclIDs;
+  std::vector<DiagWithFixIts> Diags;
+};
+
+/// Manages resources, required by clangd. Allows to rebuild file with new
+/// contents, and provides AST and Preamble for it.
+class CppFile : public std::enable_shared_from_this<CppFile> {
+public:
+  // We only allow to create CppFile as shared_ptr, because a future returned by
+  // deferRebuild will hold references to it.
+  static std::shared_ptr<CppFile>
+  Create(PathRef FileName, tooling::CompileCommand Command,
+         std::shared_ptr<PCHContainerOperations> PCHs, clangd::Logger &Logger);
+
+private:
+  CppFile(PathRef FileName, tooling::CompileCommand Command,
+          std::shared_ptr<PCHContainerOperations> PCHs, clangd::Logger &Logger);
+
+public:
+  CppFile(CppFile const &) = delete;
+  CppFile(CppFile &&) = delete;
+
+  /// Cancels a scheduled rebuild, if any, and sets AST and Preamble to nulls.
+  /// If a rebuild is in progress, will wait for it to finish.
+  void cancelRebuild();
+
+  /// Similar to deferRebuild, but sets both Preamble and AST to nulls instead
+  /// of doing an actual parsing. Returned function is a deferred computation
+  /// that will wait for any ongoing rebuilds to finish and actually set the AST
+  /// and Preamble to nulls. It can be run on a different thread. This function
+  /// is useful to cancel ongoing rebuilds, if any, before removing CppFile.
+  UniqueFunction<void()> deferCancelRebuild();
+
+  /// Rebuild AST and Preamble synchronously on the calling thread.
+  /// Returns a list of diagnostics or a llvm::None, if another rebuild was
+  /// requested in parallel (effectively cancelling this rebuild) before
+  /// diagnostics were produced.
+  llvm::Optional<std::vector<DiagWithFixIts>>
+  rebuild(StringRef NewContents, IntrusiveRefCntPtr<vfs::FileSystem> VFS);
+
+  /// Schedule a rebuild and return a deferred computation that will finish the
+  /// rebuild, that can be called on a different thread.
+  /// After calling this method, resources, available via futures returned by
+  /// getPreamble() and getAST(), will be waiting for rebuild to finish. A
+  /// continuation fininshing rebuild, returned by this function, must be
+  /// computed(i.e., operator() must be called on it) in order to make those
+  /// resources ready. If deferRebuild is called again before the rebuild is
+  /// finished (either because returned future had not been called or because it
+  /// had not returned yet), the previous rebuild request is cancelled and the
+  /// resource futures (returned by getPreamble() or getAST()) that were not
+  /// ready will be waiting for the last rebuild to finish instead.
+  /// The future to finish rebuild returns a list of diagnostics built during
+  /// reparse, or None, if another deferRebuild was called before this
+  /// rebuild was finished.
+  UniqueFunction<llvm::Optional<std::vector<DiagWithFixIts>>()>
+  deferRebuild(StringRef NewContents, IntrusiveRefCntPtr<vfs::FileSystem> VFS);
+
+  /// Returns a future to get the most fresh PreambleData for a file. The
+  /// future will wait until the Preamble is rebuilt.
+  std::shared_future<std::shared_ptr<const PreambleData>> getPreamble() const;
+  /// Return some preamble for a file. It might be stale, but won't wait for
+  /// rebuild to finish.
+  std::shared_ptr<const PreambleData> getPossiblyStalePreamble() const;
+
+  /// Returns a future to get the most fresh AST for a file. Returned AST is
+  /// wrapped to prevent concurrent accesses.
+  /// We use std::shared_ptr here because MVSC fails to compile non-copyable
+  /// classes as template arguments of promise/future. It is guaranteed to
+  /// always be non-null.
+  std::shared_future<std::shared_ptr<ParsedASTWrapper>> getAST() const;
+
+  /// Get CompileCommand used to build this CppFile.
+  tooling::CompileCommand const &getCompileCommand() const;
+
+private:
+  /// A helper guard that manages the state of CppFile during rebuild.
+  class RebuildGuard {
+  public:
+    RebuildGuard(CppFile &File, unsigned RequestRebuildCounter);
+    ~RebuildGuard();
+
+    bool wasCancelledBeforeConstruction() const;
+
+  private:
+    CppFile &File;
+    unsigned RequestRebuildCounter;
+    bool WasCancelledBeforeConstruction;
+  };
+
+  Path FileName;
+  tooling::CompileCommand Command;
+
+  /// Mutex protects all fields, declared below it, FileName and Command are not
+  /// mutated.
+  mutable std::mutex Mutex;
+  /// A counter to cancel old rebuilds.
+  unsigned RebuildCounter;
+  /// Used to wait when rebuild is finished before starting another one.
+  bool RebuildInProgress;
+  /// Condition variable to indicate changes to RebuildInProgress.
+  std::condition_variable RebuildCond;
+
+  /// Promise and future for the latests AST. Fulfilled during rebuild.
+  /// We use std::shared_ptr here because MVSC fails to compile non-copyable
+  /// classes as template arguments of promise/future.
+  std::promise<std::shared_ptr<ParsedASTWrapper>> ASTPromise;
+  std::shared_future<std::shared_ptr<ParsedASTWrapper>> ASTFuture;
+
+  /// Promise and future for the latests Preamble. Fulfilled during rebuild.
+  std::promise<std::shared_ptr<const PreambleData>> PreamblePromise;
+  std::shared_future<std::shared_ptr<const PreambleData>> PreambleFuture;
+  /// Latest preamble that was built. May be stale, but always available without
+  /// waiting for rebuild to finish.
+  std::shared_ptr<const PreambleData> LatestAvailablePreamble;
+  /// Utility class, required by clang.
+  std::shared_ptr<PCHContainerOperations> PCHs;
+  /// Used for logging various messages.
+  clangd::Logger &Logger;
+};
+
+/// Get code completions at a specified \p Pos in \p FileName.
+std::vector<CompletionItem>
+codeComplete(PathRef FileName, tooling::CompileCommand Command,
+             PrecompiledPreamble const *Preamble, StringRef Contents,
+             Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+             std::shared_ptr<PCHContainerOperations> PCHs,
+             bool SnippetCompletions, clangd::Logger &Logger);
+
+/// Get signature help at a specified \p Pos in \p FileName.
+SignatureHelp signatureHelp(PathRef FileName, tooling::CompileCommand Command,
+                            PrecompiledPreamble const *Preamble,
+                            StringRef Contents, Position Pos,
+                            IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+                            std::shared_ptr<PCHContainerOperations> PCHs,
+                            clangd::Logger &Logger);
+
+/// Get definition of symbol at a specified \p Pos.
+std::vector<Location> findDefinitions(ParsedAST &AST, Position Pos,
+                                      clangd::Logger &Logger);
+
+/// For testing/debugging purposes. Note that this method deserializes all
+/// unserialized Decls, so use with care.
+void dumpAST(ParsedAST &AST, llvm::raw_ostream &OS);
+
 } // namespace clangd
 } // namespace clang
 #endif
diff --git a/clangd/ClangdUnitStore.cpp b/clangd/ClangdUnitStore.cpp
index 56e6f54..64abb46 100644
--- a/clangd/ClangdUnitStore.cpp
+++ b/clangd/ClangdUnitStore.cpp
@@ -9,26 +9,70 @@
 
 #include "ClangdUnitStore.h"
 #include "llvm/Support/Path.h"
+#include <algorithm>
 
 using namespace clang::clangd;
 using namespace clang;
 
-void ClangdUnitStore::removeUnitIfPresent(PathRef File) {
+std::shared_ptr<CppFile> CppFileCollection::removeIfPresent(PathRef File) {
   std::lock_guard<std::mutex> Lock(Mutex);
 
   auto It = OpenedFiles.find(File);
   if (It == OpenedFiles.end())
-    return;
+    return nullptr;
+
+  std::shared_ptr<CppFile> Result = It->second;
   OpenedFiles.erase(It);
+  return Result;
 }
 
-std::vector<tooling::CompileCommand> ClangdUnitStore::getCompileCommands(GlobalCompilationDatabase &CDB, PathRef File) {
-  std::vector<tooling::CompileCommand> Commands = CDB.getCompileCommands(File);
-  if (Commands.empty()) {
-    // Add a fake command line if we know nothing.
-    Commands.push_back(tooling::CompileCommand(
-        llvm::sys::path::parent_path(File), llvm::sys::path::filename(File),
-        {"clang", "-fsyntax-only", File.str()}, ""));
+CppFileCollection::RecreateResult
+CppFileCollection::recreateFileIfCompileCommandChanged(
+    PathRef File, PathRef ResourceDir, GlobalCompilationDatabase &CDB,
+    std::shared_ptr<PCHContainerOperations> PCHs,
+    IntrusiveRefCntPtr<vfs::FileSystem> VFS, clangd::Logger &Logger) {
+  auto NewCommand = getCompileCommand(CDB, File, ResourceDir);
+
+  std::lock_guard<std::mutex> Lock(Mutex);
+
+  RecreateResult Result;
+
+  auto It = OpenedFiles.find(File);
+  if (It == OpenedFiles.end()) {
+    It = OpenedFiles
+             .try_emplace(File, CppFile::Create(File, std::move(NewCommand),
+                                                std::move(PCHs), Logger))
+             .first;
+  } else if (!compileCommandsAreEqual(It->second->getCompileCommand(),
+                                      NewCommand)) {
+    Result.RemovedFile = std::move(It->second);
+    It->second =
+        CppFile::Create(File, std::move(NewCommand), std::move(PCHs), Logger);
   }
-  return Commands;
+  Result.FileInCollection = It->second;
+  return Result;
+}
+
+tooling::CompileCommand
+CppFileCollection::getCompileCommand(GlobalCompilationDatabase &CDB,
+                                     PathRef File, PathRef ResourceDir) {
+  std::vector<tooling::CompileCommand> Commands = CDB.getCompileCommands(File);
+  if (Commands.empty())
+    // Add a fake command line if we know nothing.
+    Commands.push_back(getDefaultCompileCommand(File));
+
+  // Inject the resource dir.
+  // FIXME: Don't overwrite it if it's already there.
+  Commands.front().CommandLine.push_back("-resource-dir=" +
+                                         std::string(ResourceDir));
+  return std::move(Commands.front());
+}
+
+bool CppFileCollection::compileCommandsAreEqual(
+    tooling::CompileCommand const &LHS, tooling::CompileCommand const &RHS) {
+  // tooling::CompileCommand.Output is ignored, it's not relevant for clangd.
+  return LHS.Directory == RHS.Directory &&
+         LHS.CommandLine.size() == RHS.CommandLine.size() &&
+         std::equal(LHS.CommandLine.begin(), LHS.CommandLine.end(),
+                    RHS.CommandLine.begin());
 }
diff --git a/clangd/ClangdUnitStore.h b/clangd/ClangdUnitStore.h
index baca85c..0428883 100644
--- a/clangd/ClangdUnitStore.h
+++ b/clangd/ClangdUnitStore.h
@@ -1,4 +1,4 @@
-//===--- ClangdUnitStore.h - A ClangdUnits container -------------*-C++-*-===//
+//===--- ClangdUnitStore.h - A container of CppFiles -------------*-C++-*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -20,85 +20,70 @@
 namespace clang {
 namespace clangd {
 
-/// Thread-safe collection of ASTs built for specific files. Provides
-/// synchronized access to ASTs.
-class ClangdUnitStore {
+class Logger;
+
+/// Thread-safe mapping from FileNames to CppFile.
+class CppFileCollection {
 public:
-  /// Run specified \p Action on the ClangdUnit for \p File.
-  /// If the file is not present in ClangdUnitStore, a new ClangdUnit will be
-  /// created from the \p FileContents. If the file is already present in the
-  /// store, ClangdUnit::reparse will be called with the new contents before
-  /// running \p Action.
-  template <class Func>
-  void runOnUnit(PathRef File, StringRef FileContents,
-                 GlobalCompilationDatabase &CDB,
-                 std::shared_ptr<PCHContainerOperations> PCHs,
-                 IntrusiveRefCntPtr<vfs::FileSystem> VFS, Func Action) {
-    runOnUnitImpl(File, FileContents, CDB, PCHs, /*ReparseBeforeAction=*/true,
-                  VFS, std::forward<Func>(Action));
-  }
-
-  /// Run specified \p Action on the ClangdUnit for \p File.
-  /// If the file is not present in ClangdUnitStore, a new ClangdUnit will be
-  /// created from the \p FileContents. If the file is already present in the
-  /// store, the \p Action will be run directly on it.
-  template <class Func>
-  void runOnUnitWithoutReparse(PathRef File, StringRef FileContents,
-                               GlobalCompilationDatabase &CDB,
-                               std::shared_ptr<PCHContainerOperations> PCHs,
-                               IntrusiveRefCntPtr<vfs::FileSystem> VFS,
-                               Func Action) {
-    runOnUnitImpl(File, FileContents, CDB, PCHs, /*ReparseBeforeAction=*/false,
-                  VFS, std::forward<Func>(Action));
-  }
-
-  /// Run the specified \p Action on the ClangdUnit for \p File.
-  /// Unit for \p File should exist in the store.
-  template <class Func>
-  void runOnExistingUnit(PathRef File, Func Action) {
+  std::shared_ptr<CppFile> getOrCreateFile(
+      PathRef File, PathRef ResourceDir, GlobalCompilationDatabase &CDB,
+      std::shared_ptr<PCHContainerOperations> PCHs,
+      IntrusiveRefCntPtr<vfs::FileSystem> VFS, clangd::Logger &Logger) {
     std::lock_guard<std::mutex> Lock(Mutex);
 
     auto It = OpenedFiles.find(File);
-    assert(It != OpenedFiles.end() && "File is not in OpenedFiles");
-
-    Action(It->second);
-  }
-
-  /// Remove ClangdUnit for \p File, if any
-  void removeUnitIfPresent(PathRef File);
-
-private:
-  /// Run specified \p Action on the ClangdUnit for \p File.
-  template <class Func>
-  void runOnUnitImpl(PathRef File, StringRef FileContents,
-                     GlobalCompilationDatabase &CDB,
-                     std::shared_ptr<PCHContainerOperations> PCHs,
-                     bool ReparseBeforeAction,
-                     IntrusiveRefCntPtr<vfs::FileSystem> VFS, Func Action) {
-    std::lock_guard<std::mutex> Lock(Mutex);
-
-    auto Commands = getCompileCommands(CDB, File);
-    assert(!Commands.empty() &&
-           "getCompileCommands should add default command");
-    VFS->setCurrentWorkingDirectory(Commands.front().Directory);
-
-    auto It = OpenedFiles.find(File);
     if (It == OpenedFiles.end()) {
+      auto Command = getCompileCommand(CDB, File, ResourceDir);
+
       It = OpenedFiles
-               .insert(std::make_pair(
-                   File, ClangdUnit(File, FileContents, PCHs, Commands, VFS)))
+               .try_emplace(File, CppFile::Create(File, std::move(Command),
+                                                  std::move(PCHs), Logger))
                .first;
-    } else if (ReparseBeforeAction) {
-      It->second.reparse(FileContents, VFS);
     }
-    return Action(It->second);
+    return It->second;
   }
 
-  std::vector<tooling::CompileCommand>
-  getCompileCommands(GlobalCompilationDatabase &CDB, PathRef File);
+  struct RecreateResult {
+    /// A CppFile, stored in this CppFileCollection for the corresponding
+    /// filepath after calling recreateFileIfCompileCommandChanged.
+    std::shared_ptr<CppFile> FileInCollection;
+    /// If a new CppFile had to be created to account for changed
+    /// CompileCommand, a previous CppFile instance will be returned in this
+    /// field.
+    std::shared_ptr<CppFile> RemovedFile;
+  };
+
+  /// Similar to getOrCreateFile, but will replace a current CppFile for \p File
+  /// with a new one if CompileCommand, provided by \p CDB has changed.
+  /// If a currently stored CppFile had to be replaced, the previous instance
+  /// will be returned in RecreateResult.RemovedFile.
+  RecreateResult recreateFileIfCompileCommandChanged(
+      PathRef File, PathRef ResourceDir, GlobalCompilationDatabase &CDB,
+      std::shared_ptr<PCHContainerOperations> PCHs,
+      IntrusiveRefCntPtr<vfs::FileSystem> VFS, clangd::Logger &Logger);
+
+  std::shared_ptr<CppFile> getFile(PathRef File) {
+    std::lock_guard<std::mutex> Lock(Mutex);
+
+    auto It = OpenedFiles.find(File);
+    if (It == OpenedFiles.end())
+      return nullptr;
+    return It->second;
+  }
+
+  /// Removes a CppFile, stored for \p File, if it's inside collection and
+  /// returns it.
+  std::shared_ptr<CppFile> removeIfPresent(PathRef File);
+
+private:
+  tooling::CompileCommand getCompileCommand(GlobalCompilationDatabase &CDB,
+                                            PathRef File, PathRef ResourceDir);
+
+  bool compileCommandsAreEqual(tooling::CompileCommand const &LHS,
+                               tooling::CompileCommand const &RHS);
 
   std::mutex Mutex;
-  llvm::StringMap<ClangdUnit> OpenedFiles;
+  llvm::StringMap<std::shared_ptr<CppFile>> OpenedFiles;
 };
 } // namespace clangd
 } // namespace clang
diff --git a/clangd/DraftStore.h b/clangd/DraftStore.h
index c4e31e7..2dd7184 100644
--- a/clangd/DraftStore.h
+++ b/clangd/DraftStore.h
@@ -13,6 +13,7 @@
 #include "Path.h"
 #include "clang/Basic/LLVM.h"
 #include "llvm/ADT/StringMap.h"
+#include <cstdint>
 #include <mutex>
 #include <string>
 #include <vector>
@@ -20,8 +21,8 @@
 namespace clang {
 namespace clangd {
 
-/// Using 'unsigned' here to avoid undefined behaviour on overflow.
-typedef unsigned DocVersion;
+/// Using unsigned int type here to avoid undefined behaviour on overflow.
+typedef uint64_t DocVersion;
 
 /// Document draft with a version of this draft.
 struct VersionedDraft {
diff --git a/clangd/Function.h b/clangd/Function.h
new file mode 100644
index 0000000..d1bc94b
--- /dev/null
+++ b/clangd/Function.h
@@ -0,0 +1,139 @@
+//===--- Function.h - Utility callable wrappers  -----------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides an analogue to std::function that supports move semantics.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FUNCTION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FUNCTION_H
+
+#include "llvm/ADT/STLExtras.h"
+#include <cassert>
+#include <memory>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+namespace clang {
+namespace clangd {
+
+/// A move-only type-erasing function wrapper. Similar to `std::function`, but
+/// allows to store move-only callables.
+template <class> class UniqueFunction;
+
+template <class Ret, class... Args> class UniqueFunction<Ret(Args...)> {
+public:
+  UniqueFunction() = default;
+  UniqueFunction(std::nullptr_t) : UniqueFunction(){};
+
+  UniqueFunction(UniqueFunction const &) = delete;
+  UniqueFunction &operator=(UniqueFunction const &) = delete;
+
+  UniqueFunction(UniqueFunction &&) noexcept = default;
+  UniqueFunction &operator=(UniqueFunction &&) noexcept = default;
+
+  template <class Callable>
+  UniqueFunction(Callable &&Func)
+      : CallablePtr(llvm::make_unique<
+                    FunctionCallImpl<typename std::decay<Callable>::type>>(
+            std::forward<Callable>(Func))) {}
+
+  operator bool() { return CallablePtr; }
+
+  Ret operator()(Args... As) {
+    assert(CallablePtr);
+    return CallablePtr->Call(std::forward<Args>(As)...);
+  }
+
+private:
+  class FunctionCallBase {
+  public:
+    virtual ~FunctionCallBase() = default;
+    virtual Ret Call(Args... As) = 0;
+  };
+
+  template <class Callable>
+  class FunctionCallImpl final : public FunctionCallBase {
+    static_assert(
+        std::is_same<Callable, typename std::decay<Callable>::type>::value,
+        "FunctionCallImpl must be instanstiated with std::decay'ed types");
+
+  public:
+    FunctionCallImpl(Callable Func) : Func(std::move(Func)) {}
+
+    Ret Call(Args... As) override { return Func(std::forward<Args>(As)...); }
+
+  private:
+    Callable Func;
+  };
+
+  std::unique_ptr<FunctionCallBase> CallablePtr;
+};
+
+/// Stores a callable object (Func) and arguments (Args) and allows to call the
+/// callable with provided arguments later using `operator ()`. The arguments
+/// are std::forward'ed into the callable in the body of `operator()`. Therefore
+/// `operator()` can only be called once, as some of the arguments could be
+/// std::move'ed into the callable on first call.
+template <class Func, class... Args> struct ForwardBinder {
+  using Tuple = std::tuple<typename std::decay<Func>::type,
+                           typename std::decay<Args>::type...>;
+  Tuple FuncWithArguments;
+#ifndef NDEBUG
+  bool WasCalled = false;
+#endif
+
+public:
+  ForwardBinder(Tuple FuncWithArguments)
+      : FuncWithArguments(std::move(FuncWithArguments)) {}
+
+private:
+  template <std::size_t... Indexes, class... RestArgs>
+  auto CallImpl(llvm::integer_sequence<std::size_t, Indexes...> Seq,
+                RestArgs &&... Rest)
+      -> decltype(std::get<0>(this->FuncWithArguments)(
+          std::forward<Args>(std::get<Indexes + 1>(this->FuncWithArguments))...,
+          std::forward<RestArgs>(Rest)...)) {
+    return std::get<0>(this->FuncWithArguments)(
+        std::forward<Args>(std::get<Indexes + 1>(this->FuncWithArguments))...,
+        std::forward<RestArgs>(Rest)...);
+  }
+
+public:
+  template <class... RestArgs>
+  auto operator()(RestArgs &&... Rest)
+      -> decltype(this->CallImpl(llvm::index_sequence_for<Args...>(),
+                                 std::forward<RestArgs>(Rest)...)) {
+
+#ifndef NDEBUG
+    assert(!WasCalled && "Can only call result of BindWithForward once.");
+    WasCalled = true;
+#endif
+    return CallImpl(llvm::index_sequence_for<Args...>(),
+                    std::forward<RestArgs>(Rest)...);
+  }
+};
+
+/// Creates an object that stores a callable (\p F) and first arguments to the
+/// callable (\p As) and allows to call \p F with \Args at a later point.
+/// Similar to std::bind, but also works with move-only \p F and \p As.
+///
+/// The returned object must be called no more than once, as \p As are
+/// std::forwarded'ed (therefore can be moved) into \p F during the call.
+template <class Func, class... Args>
+ForwardBinder<Func, Args...> BindWithForward(Func F, Args &&... As) {
+  return ForwardBinder<Func, Args...>(
+      std::make_tuple(std::forward<Func>(F), std::forward<Args>(As)...));
+}
+
+} // namespace clangd
+} // namespace clang
+
+#endif
diff --git a/clangd/GlobalCompilationDatabase.cpp b/clangd/GlobalCompilationDatabase.cpp
index 91d7702..834d992 100644
--- a/clangd/GlobalCompilationDatabase.cpp
+++ b/clangd/GlobalCompilationDatabase.cpp
@@ -8,21 +8,86 @@
 //===---------------------------------------------------------------------===//
 
 #include "GlobalCompilationDatabase.h"
+#include "Logger.h"
 #include "clang/Tooling/CompilationDatabase.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
 
-using namespace clang::clangd;
-using namespace clang;
+namespace clang {
+namespace clangd {
+
+static void addExtraFlags(tooling::CompileCommand &Command,
+                          const std::vector<std::string> &ExtraFlags) {
+  if (ExtraFlags.empty())
+    return;
+  assert(Command.CommandLine.size() >= 2 &&
+         "Expected a command line containing at least 2 arguments, the "
+         "compiler binary and the output file");
+  // The last argument of CommandLine is the name of the input file.
+  // Add ExtraFlags before it.
+  auto It = Command.CommandLine.end();
+  --It;
+  Command.CommandLine.insert(It, ExtraFlags.begin(), ExtraFlags.end());
+}
+
+tooling::CompileCommand getDefaultCompileCommand(PathRef File) {
+  std::vector<std::string> CommandLine{"clang", "-fsyntax-only", File.str()};
+  return tooling::CompileCommand(llvm::sys::path::parent_path(File),
+                                 llvm::sys::path::filename(File), CommandLine,
+                                 /*Output=*/"");
+}
+
+DirectoryBasedGlobalCompilationDatabase::
+    DirectoryBasedGlobalCompilationDatabase(
+        clangd::Logger &Logger, llvm::Optional<Path> CompileCommandsDir)
+    : Logger(Logger), CompileCommandsDir(std::move(CompileCommandsDir)) {}
 
 std::vector<tooling::CompileCommand>
 DirectoryBasedGlobalCompilationDatabase::getCompileCommands(PathRef File) {
   std::vector<tooling::CompileCommand> Commands;
 
   auto CDB = getCompilationDatabase(File);
-  if (!CDB)
-    return {};
-  return CDB->getCompileCommands(File);
+  if (CDB)
+    Commands = CDB->getCompileCommands(File);
+  if (Commands.empty())
+    Commands.push_back(getDefaultCompileCommand(File));
+
+  auto It = ExtraFlagsForFile.find(File);
+  if (It != ExtraFlagsForFile.end()) {
+    // Append the user-specified flags to the compile commands.
+    for (tooling::CompileCommand &Command : Commands)
+      addExtraFlags(Command, It->second);
+  }
+
+  return Commands;
+}
+
+void DirectoryBasedGlobalCompilationDatabase::setExtraFlagsForFile(
+    PathRef File, std::vector<std::string> ExtraFlags) {
+  ExtraFlagsForFile[File] = std::move(ExtraFlags);
+}
+
+tooling::CompilationDatabase *
+DirectoryBasedGlobalCompilationDatabase::tryLoadDatabaseFromPath(PathRef File) {
+
+  namespace path = llvm::sys::path;
+  auto CachedIt = CompilationDatabases.find(File);
+
+  assert((path::is_absolute(File, path::Style::posix) ||
+          path::is_absolute(File, path::Style::windows)) &&
+         "path must be absolute");
+
+  if (CachedIt != CompilationDatabases.end())
+    return CachedIt->second.get();
+  std::string Error = "";
+  auto CDB = tooling::CompilationDatabase::loadFromDirectory(File, Error);
+  if (CDB && Error.empty()) {
+    auto Result = CDB.get();
+    CompilationDatabases.insert(std::make_pair(File, std::move(CDB)));
+    return Result;
+  }
+
+  return nullptr;
 }
 
 tooling::CompilationDatabase *
@@ -30,36 +95,28 @@
   std::lock_guard<std::mutex> Lock(Mutex);
 
   namespace path = llvm::sys::path;
-
-  assert((path::is_absolute(File, path::Style::posix) ||
-          path::is_absolute(File, path::Style::windows)) &&
-         "path must be absolute");
+  if (CompileCommandsDir.hasValue()) {
+    tooling::CompilationDatabase *ReturnValue =
+        tryLoadDatabaseFromPath(CompileCommandsDir.getValue());
+    if (ReturnValue == nullptr)
+      Logger.log("Failed to find compilation database for " + Twine(File) +
+                 "in overriden directory " + CompileCommandsDir.getValue() +
+                 "\n");
+    return ReturnValue;
+  }
 
   for (auto Path = path::parent_path(File); !Path.empty();
        Path = path::parent_path(Path)) {
-
-    auto CachedIt = CompilationDatabases.find(Path);
-    if (CachedIt != CompilationDatabases.end())
-      return CachedIt->second.get();
-    std::string Error;
-    auto CDB = tooling::CompilationDatabase::loadFromDirectory(Path, Error);
-    if (!CDB) {
-      if (!Error.empty()) {
-        // FIXME(ibiryukov): logging
-        // Output.log("Error when trying to load compilation database from " +
-        //            Twine(Path) + ": " + Twine(Error) + "\n");
-      }
+    auto CDB = tryLoadDatabaseFromPath(Path);
+    if (!CDB)
       continue;
-    }
-
     // FIXME(ibiryukov): Invalidate cached compilation databases on changes
-    auto result = CDB.get();
-    CompilationDatabases.insert(std::make_pair(Path, std::move(CDB)));
-    return result;
+    return CDB;
   }
 
-  // FIXME(ibiryukov): logging
-  // Output.log("Failed to find compilation database for " + Twine(File) +
-  // "\n");
+  Logger.log("Failed to find compilation database for " + Twine(File) + "\n");
   return nullptr;
 }
+
+} // namespace clangd
+} // namespace clang
diff --git a/clangd/GlobalCompilationDatabase.h b/clangd/GlobalCompilationDatabase.h
index 933e566..c43ca0d 100644
--- a/clangd/GlobalCompilationDatabase.h
+++ b/clangd/GlobalCompilationDatabase.h
@@ -25,7 +25,12 @@
 
 namespace clangd {
 
-/// Provides compilation arguments used for building ClangdUnit.
+class Logger;
+
+/// Returns a default compile command to use for \p File.
+tooling::CompileCommand getDefaultCompileCommand(PathRef File);
+
+/// Provides compilation arguments used for parsing C and C++ files.
 class GlobalCompilationDatabase {
 public:
   virtual ~GlobalCompilationDatabase() = default;
@@ -42,17 +47,31 @@
 class DirectoryBasedGlobalCompilationDatabase
     : public GlobalCompilationDatabase {
 public:
+  DirectoryBasedGlobalCompilationDatabase(
+      clangd::Logger &Logger, llvm::Optional<Path> CompileCommandsDir);
+
   std::vector<tooling::CompileCommand>
   getCompileCommands(PathRef File) override;
 
+  void setExtraFlagsForFile(PathRef File, std::vector<std::string> ExtraFlags);
+
 private:
   tooling::CompilationDatabase *getCompilationDatabase(PathRef File);
+  tooling::CompilationDatabase *tryLoadDatabaseFromPath(PathRef File);
 
   std::mutex Mutex;
   /// Caches compilation databases loaded from directories(keys are
   /// directories).
   llvm::StringMap<std::unique_ptr<clang::tooling::CompilationDatabase>>
       CompilationDatabases;
+
+  /// Stores extra flags per file.
+  llvm::StringMap<std::vector<std::string>> ExtraFlagsForFile;
+  /// Used for logging.
+  clangd::Logger &Logger;
+  /// Used for command argument pointing to folder where compile_commands.json
+  /// is located.
+  llvm::Optional<Path> CompileCommandsDir;
 };
 } // namespace clangd
 } // namespace clang
diff --git a/clangd/JSONRPCDispatcher.cpp b/clangd/JSONRPCDispatcher.cpp
index 5deb75a..7e0aea5 100644
--- a/clangd/JSONRPCDispatcher.cpp
+++ b/clangd/JSONRPCDispatcher.cpp
@@ -37,38 +37,50 @@
   Logs.flush();
 }
 
-void Handler::handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) {
-  Output.log("Method ignored.\n");
-  // Return that this method is unsupported.
-  writeMessage(
-      R"({"jsonrpc":"2.0","id":)" + ID +
-      R"(,"error":{"code":-32601}})");
+void JSONOutput::mirrorInput(const Twine &Message) {
+  if (!InputMirror)
+    return;
+
+  *InputMirror << Message;
+  InputMirror->flush();
 }
 
-void Handler::handleNotification(llvm::yaml::MappingNode *Params) {
-  Output.log("Notification ignored.\n");
+void RequestContext::reply(const llvm::Twine &Result) {
+  if (ID.empty()) {
+    Out.log("Attempted to reply to a notification!\n");
+    return;
+  }
+  Out.writeMessage(llvm::Twine(R"({"jsonrpc":"2.0","id":)") + ID +
+                   R"(,"result":)" + Result + "}");
 }
 
-void JSONRPCDispatcher::registerHandler(StringRef Method,
-                                        std::unique_ptr<Handler> H) {
+void RequestContext::replyError(int code, const llvm::StringRef &Message) {
+  Out.log("Error " + llvm::Twine(code) + ": " + Message + "\n");
+  if (!ID.empty()) {
+    Out.writeMessage(llvm::Twine(R"({"jsonrpc":"2.0","id":)") + ID +
+                     R"(,"error":{"code":)" + llvm::Twine(code) +
+                     R"(,"message":")" + llvm::yaml::escape(Message) +
+                     R"("}})");
+  }
+}
+
+void JSONRPCDispatcher::registerHandler(StringRef Method, Handler H) {
   assert(!Handlers.count(Method) && "Handler already registered!");
   Handlers[Method] = std::move(H);
 }
 
 static void
-callHandler(const llvm::StringMap<std::unique_ptr<Handler>> &Handlers,
+callHandler(const llvm::StringMap<JSONRPCDispatcher::Handler> &Handlers,
             llvm::yaml::ScalarNode *Method, llvm::yaml::ScalarNode *Id,
-            llvm::yaml::MappingNode *Params, Handler *UnknownHandler) {
-  llvm::SmallString<10> MethodStorage;
+            llvm::yaml::MappingNode *Params,
+            const JSONRPCDispatcher::Handler &UnknownHandler, JSONOutput &Out) {
+  llvm::SmallString<64> MethodStorage;
   auto I = Handlers.find(Method->getValue(MethodStorage));
-  auto *Handler = I != Handlers.end() ? I->second.get() : UnknownHandler;
-  if (Id)
-    Handler->handleMethod(Params, Id->getRawValue());
-  else
-    Handler->handleNotification(Params);
+  auto &Handler = I != Handlers.end() ? I->second : UnknownHandler;
+  Handler(RequestContext(Out, Id ? Id->getRawValue() : ""), Params);
 }
 
-bool JSONRPCDispatcher::call(StringRef Content) const {
+bool JSONRPCDispatcher::call(StringRef Content, JSONOutput &Out) const {
   llvm::SourceMgr SM;
   llvm::yaml::Stream YAMLStream(Content, SM);
 
@@ -116,7 +128,7 @@
       // because it will break clients that put the id after params. A possible
       // fix would be to split the parsing and execution phases.
       Params = dyn_cast<llvm::yaml::MappingNode>(Value);
-      callHandler(Handlers, Method, Id, Params, UnknownHandler.get());
+      callHandler(Handlers, Method, Id, Params, UnknownHandler, Out);
       return true;
     } else {
       return false;
@@ -127,7 +139,7 @@
   // leftovers.
   if (!Method)
     return false;
-  callHandler(Handlers, Method, Id, nullptr, UnknownHandler.get());
+  callHandler(Handlers, Method, Id, nullptr, UnknownHandler, Out);
 
   return true;
 }
@@ -136,56 +148,86 @@
                                    JSONRPCDispatcher &Dispatcher,
                                    bool &IsDone) {
   while (In.good()) {
-    // A Language Server Protocol message starts with a HTTP header, delimited
-    // by \r\n.
-    std::string Line;
-    std::getline(In, Line);
-    if (!In.good() && errno == EINTR) {
-      In.clear();
-      continue;
+    // A Language Server Protocol message starts with a set of HTTP headers,
+    // delimited  by \r\n, and terminated by an empty line (\r\n).
+    unsigned long long ContentLength = 0;
+    while (In.good()) {
+      std::string Line;
+      std::getline(In, Line);
+      if (!In.good() && errno == EINTR) {
+        In.clear();
+        continue;
+      }
+
+      Out.mirrorInput(Line);
+      // Mirror '\n' that gets consumed by std::getline, but is not included in
+      // the resulting Line.
+      // Note that '\r' is part of Line, so we don't need to mirror it
+      // separately.
+      if (!In.eof())
+        Out.mirrorInput("\n");
+
+      llvm::StringRef LineRef(Line);
+
+      // We allow YAML-style comments in headers. Technically this isn't part
+      // of the LSP specification, but makes writing tests easier.
+      if (LineRef.startswith("#"))
+        continue;
+
+      // Content-Type is a specified header, but does nothing.
+      // Content-Length is a mandatory header. It specifies the length of the
+      // following JSON.
+      // It is unspecified what sequence headers must be supplied in, so we
+      // allow any sequence.
+      // The end of headers is signified by an empty line.
+      if (LineRef.consume_front("Content-Length: ")) {
+        if (ContentLength != 0) {
+          Out.log("Warning: Duplicate Content-Length header received. "
+                  "The previous value for this message (" +
+                  std::to_string(ContentLength) + ") was ignored.\n");
+        }
+
+        llvm::getAsUnsignedInteger(LineRef.trim(), 0, ContentLength);
+        continue;
+      } else if (!LineRef.trim().empty()) {
+        // It's another header, ignore it.
+        continue;
+      } else {
+        // An empty line indicates the end of headers.
+        // Go ahead and read the JSON.
+        break;
+      }
     }
 
-    // Skip empty lines.
-    llvm::StringRef LineRef(Line);
-    if (LineRef.trim().empty())
-      continue;
+    if (ContentLength > 0) {
+      // Now read the JSON. Insert a trailing null byte as required by the YAML
+      // parser.
+      std::vector<char> JSON(ContentLength + 1, '\0');
+      In.read(JSON.data(), ContentLength);
+      Out.mirrorInput(StringRef(JSON.data(), In.gcount()));
 
-    // We allow YAML-style comments. Technically this isn't part of the
-    // LSP specification, but makes writing tests easier.
-    if (LineRef.startswith("#"))
-      continue;
+      // If the stream is aborted before we read ContentLength bytes, In
+      // will have eofbit and failbit set.
+      if (!In) {
+        Out.log("Input was aborted. Read only " + std::to_string(In.gcount()) +
+                " bytes of expected " + std::to_string(ContentLength) + ".\n");
+        break;
+      }
 
-    unsigned long long Len = 0;
-    // FIXME: Content-Type is a specified header, but does nothing.
-    // Content-Length is a mandatory header. It specifies the length of the
-    // following JSON.
-    if (LineRef.consume_front("Content-Length: "))
-      llvm::getAsUnsignedInteger(LineRef.trim(), 0, Len);
-
-    // Check if the next line only contains \r\n. If not this is another header,
-    // which we ignore.
-    char NewlineBuf[2];
-    In.read(NewlineBuf, 2);
-    if (std::memcmp(NewlineBuf, "\r\n", 2) != 0)
-      continue;
-
-    // Now read the JSON. Insert a trailing null byte as required by the YAML
-    // parser.
-    std::vector<char> JSON(Len + 1, '\0');
-    In.read(JSON.data(), Len);
-
-    if (Len > 0) {
-      llvm::StringRef JSONRef(JSON.data(), Len);
+      llvm::StringRef JSONRef(JSON.data(), ContentLength);
       // Log the message.
       Out.log("<-- " + JSONRef + "\n");
 
       // Finally, execute the action for this JSON message.
-      if (!Dispatcher.call(JSONRef))
+      if (!Dispatcher.call(JSONRef, Out))
         Out.log("JSON dispatch failed!\n");
 
       // If we're done, exit the loop.
       if (IsDone)
         break;
+    } else {
+      Out.log("Warning: Missing Content-Length header, or message has zero "
+              "length.\n");
     }
   }
 }
diff --git a/clangd/JSONRPCDispatcher.h b/clangd/JSONRPCDispatcher.h
index 349ac90..9071e42 100644
--- a/clangd/JSONRPCDispatcher.h
+++ b/clangd/JSONRPCDispatcher.h
@@ -10,7 +10,9 @@
 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSONRPCDISPATCHER_H
 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSONRPCDISPATCHER_H
 
+#include "Logger.h"
 #include "clang/Basic/LLVM.h"
+#include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/Support/YAMLParser.h"
 #include <iosfwd>
@@ -21,63 +23,69 @@
 
 /// Encapsulates output and logs streams and provides thread-safe access to
 /// them.
-class JSONOutput {
+class JSONOutput : public Logger {
 public:
-  JSONOutput(llvm::raw_ostream &Outs, llvm::raw_ostream &Logs)
-      : Outs(Outs), Logs(Logs) {}
+  JSONOutput(llvm::raw_ostream &Outs, llvm::raw_ostream &Logs,
+             llvm::raw_ostream *InputMirror = nullptr)
+      : Outs(Outs), Logs(Logs), InputMirror(InputMirror) {}
 
   /// Emit a JSONRPC message.
   void writeMessage(const Twine &Message);
 
   /// Write to the logging stream.
-  void log(const Twine &Message);
+  /// No newline is implicitly added. (TODO: we should fix this!)
+  void log(const Twine &Message) override;
+
+  /// Mirror \p Message into InputMirror stream. Does nothing if InputMirror is
+  /// null.
+  /// Unlike other methods of JSONOutput, mirrorInput is not thread-safe.
+  void mirrorInput(const Twine &Message);
 
 private:
   llvm::raw_ostream &Outs;
   llvm::raw_ostream &Logs;
+  llvm::raw_ostream *InputMirror;
 
   std::mutex StreamMutex;
 };
 
-/// Callback for messages sent to the server, called by the JSONRPCDispatcher.
-class Handler {
+/// Context object passed to handlers to allow replies.
+class RequestContext {
 public:
-  Handler(JSONOutput &Output) : Output(Output) {}
-  virtual ~Handler() = default;
+  RequestContext(JSONOutput &Out, StringRef ID) : Out(Out), ID(ID) {}
 
-  /// Called when the server receives a method call. This is supposed to return
-  /// a result on Outs. The default implementation returns an "unknown method"
-  /// error to the client and logs a warning.
-  virtual void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID);
-  /// Called when the server receives a notification. No result should be
-  /// written to Outs. The default implemetation logs a warning.
-  virtual void handleNotification(llvm::yaml::MappingNode *Params);
+  /// Sends a successful reply. Result should be well-formed JSON.
+  void reply(const Twine &Result);
+  /// Sends an error response to the client, and logs it.
+  void replyError(int code, const llvm::StringRef &Message);
 
-protected:
-  JSONOutput &Output;
-
-  /// Helper to write a JSONRPC result to Output.
-  void writeMessage(const Twine &Message) { Output.writeMessage(Message); }
+private:
+  JSONOutput &Out;
+  llvm::SmallString<64> ID; // Valid JSON, or empty for a notification.
 };
 
 /// Main JSONRPC entry point. This parses the JSONRPC "header" and calls the
 /// registered Handler for the method received.
 class JSONRPCDispatcher {
 public:
+  // A handler responds to requests for a particular method name.
+  using Handler =
+      std::function<void(RequestContext, llvm::yaml::MappingNode *)>;
+
   /// Create a new JSONRPCDispatcher. UnknownHandler is called when an unknown
   /// method is received.
-  JSONRPCDispatcher(std::unique_ptr<Handler> UnknownHandler)
+  JSONRPCDispatcher(Handler UnknownHandler)
       : UnknownHandler(std::move(UnknownHandler)) {}
 
   /// Registers a Handler for the specified Method.
-  void registerHandler(StringRef Method, std::unique_ptr<Handler> H);
+  void registerHandler(StringRef Method, Handler H);
 
   /// Parses a JSONRPC message and calls the Handler for it.
-  bool call(StringRef Content) const;
+  bool call(StringRef Content, JSONOutput &Out) const;
 
 private:
-  llvm::StringMap<std::unique_ptr<Handler>> Handlers;
-  std::unique_ptr<Handler> UnknownHandler;
+  llvm::StringMap<Handler> Handlers;
+  Handler UnknownHandler;
 };
 
 /// Parses input queries from LSP client (coming from \p In) and runs call
diff --git a/clangd/Logger.cpp b/clangd/Logger.cpp
new file mode 100644
index 0000000..0448c6f
--- /dev/null
+++ b/clangd/Logger.cpp
@@ -0,0 +1,19 @@
+//===--- Logger.cpp - Logger interface for clangd -------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Logger.h"
+
+using namespace clang::clangd;
+
+EmptyLogger &EmptyLogger::getInstance() {
+  static EmptyLogger Logger;
+  return Logger;
+}
+
+void EmptyLogger::log(const llvm::Twine &Message) {}
diff --git a/clangd/Logger.h b/clangd/Logger.h
new file mode 100644
index 0000000..7cf0556
--- /dev/null
+++ b/clangd/Logger.h
@@ -0,0 +1,41 @@
+//===--- Logger.h - Logger interface for clangd ------------------*- 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_CLANGD_LOGGER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_LOGGER_H
+
+#include "llvm/ADT/Twine.h"
+
+namespace clang {
+namespace clangd {
+
+/// Interface to allow custom logging in clangd.
+class Logger {
+public:
+  virtual ~Logger() = default;
+
+  /// Implementations of this method must be thread-safe.
+  virtual void log(const llvm::Twine &Message) = 0;
+};
+
+/// Logger implementation that ignores all messages.
+class EmptyLogger : public Logger {
+public:
+  static EmptyLogger &getInstance();
+
+  void log(const llvm::Twine &Message) override;
+
+private:
+  EmptyLogger() = default;
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif
diff --git a/clangd/Protocol.cpp b/clangd/Protocol.cpp
index 016d8fd..509e596 100644
--- a/clangd/Protocol.cpp
+++ b/clangd/Protocol.cpp
@@ -13,13 +13,23 @@
 //===----------------------------------------------------------------------===//
 
 #include "Protocol.h"
+#include "Logger.h"
+
 #include "clang/Basic/LLVM.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Support/Format.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
 using namespace clang::clangd;
 
+namespace {
+void logIgnoredField(llvm::StringRef KeyValue, clangd::Logger &Logger) {
+  Logger.log(llvm::formatv("Ignored unknown field \"{0}\"\n", KeyValue));
+}
+} // namespace
 
 URI URI::fromUri(llvm::StringRef uri) {
   URI Result;
@@ -53,12 +63,11 @@
   return URI::fromUri(Param->getValue(Storage));
 }
 
-std::string URI::unparse(const URI &U) {
-  return U.uri;
-}
+std::string URI::unparse(const URI &U) { return "\"" + U.uri + "\""; }
 
 llvm::Optional<TextDocumentIdentifier>
-TextDocumentIdentifier::parse(llvm::yaml::MappingNode *Params) {
+TextDocumentIdentifier::parse(llvm::yaml::MappingNode *Params,
+                              clangd::Logger &Logger) {
   TextDocumentIdentifier Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -77,13 +86,14 @@
     } else if (KeyValue == "version") {
       // FIXME: parse version, but only for VersionedTextDocumentIdentifiers.
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
-llvm::Optional<Position> Position::parse(llvm::yaml::MappingNode *Params) {
+llvm::Optional<Position> Position::parse(llvm::yaml::MappingNode *Params,
+                                         clangd::Logger &Logger) {
   Position Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -109,7 +119,7 @@
         return llvm::None;
       Result.character = Val;
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
@@ -122,7 +132,8 @@
   return Result;
 }
 
-llvm::Optional<Range> Range::parse(llvm::yaml::MappingNode *Params) {
+llvm::Optional<Range> Range::parse(llvm::yaml::MappingNode *Params,
+                                   clangd::Logger &Logger) {
   Range Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -138,17 +149,17 @@
 
     llvm::SmallString<10> Storage;
     if (KeyValue == "start") {
-      auto Parsed = Position::parse(Value);
+      auto Parsed = Position::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.start = std::move(*Parsed);
     } else if (KeyValue == "end") {
-      auto Parsed = Position::parse(Value);
+      auto Parsed = Position::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.end = std::move(*Parsed);
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
@@ -162,8 +173,17 @@
   return Result;
 }
 
+std::string Location::unparse(const Location &P) {
+  std::string Result;
+  llvm::raw_string_ostream(Result) << llvm::format(
+      R"({"uri": %s, "range": %s})", URI::unparse(P.uri).c_str(),
+      Range::unparse(P.range).c_str());
+  return Result;
+}
+
 llvm::Optional<TextDocumentItem>
-TextDocumentItem::parse(llvm::yaml::MappingNode *Params) {
+TextDocumentItem::parse(llvm::yaml::MappingNode *Params,
+                        clangd::Logger &Logger) {
   TextDocumentItem Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -190,13 +210,44 @@
     } else if (KeyValue == "text") {
       Result.text = Value->getValue(Storage);
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
-llvm::Optional<TextEdit> TextEdit::parse(llvm::yaml::MappingNode *Params) {
+llvm::Optional<Metadata> Metadata::parse(llvm::yaml::MappingNode *Params,
+                                         clangd::Logger &Logger) {
+  Metadata Result;
+  for (auto &NextKeyValue : *Params) {
+    auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
+    if (!KeyString)
+      return llvm::None;
+
+    llvm::SmallString<10> KeyStorage;
+    StringRef KeyValue = KeyString->getValue(KeyStorage);
+    auto *Value = NextKeyValue.getValue();
+
+    llvm::SmallString<10> Storage;
+    if (KeyValue == "extraFlags") {
+      auto *Seq = dyn_cast<llvm::yaml::SequenceNode>(Value);
+      if (!Seq)
+        return llvm::None;
+      for (auto &Item : *Seq) {
+        auto *Node = dyn_cast<llvm::yaml::ScalarNode>(&Item);
+        if (!Node)
+          return llvm::None;
+        Result.extraFlags.push_back(Node->getValue(Storage));
+      }
+    } else {
+      logIgnoredField(KeyValue, Logger);
+    }
+  }
+  return Result;
+}
+
+llvm::Optional<TextEdit> TextEdit::parse(llvm::yaml::MappingNode *Params,
+                                         clangd::Logger &Logger) {
   TextEdit Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -212,7 +263,7 @@
       auto *Map = dyn_cast<llvm::yaml::MappingNode>(Value);
       if (!Map)
         return llvm::None;
-      auto Parsed = Range::parse(Map);
+      auto Parsed = Range::parse(Map, Logger);
       if (!Parsed)
         return llvm::None;
       Result.range = std::move(*Parsed);
@@ -222,7 +273,7 @@
         return llvm::None;
       Result.newText = Node->getValue(Storage);
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
@@ -236,8 +287,71 @@
   return Result;
 }
 
+namespace {
+TraceLevel getTraceLevel(llvm::StringRef TraceLevelStr,
+                         clangd::Logger &Logger) {
+  if (TraceLevelStr == "off")
+    return TraceLevel::Off;
+  else if (TraceLevelStr == "messages")
+    return TraceLevel::Messages;
+  else if (TraceLevelStr == "verbose")
+    return TraceLevel::Verbose;
+
+  Logger.log(llvm::formatv("Unknown trace level \"{0}\"\n", TraceLevelStr));
+  return TraceLevel::Off;
+}
+} // namespace
+
+llvm::Optional<InitializeParams>
+InitializeParams::parse(llvm::yaml::MappingNode *Params,
+                        clangd::Logger &Logger) {
+  // If we don't understand the params, proceed with default parameters.
+  auto ParseFailure = [&] {
+    Logger.log("Failed to decode InitializeParams\n");
+    return InitializeParams();
+  };
+  InitializeParams Result;
+  for (auto &NextKeyValue : *Params) {
+    auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
+    if (!KeyString)
+      return ParseFailure();
+
+    llvm::SmallString<10> KeyStorage;
+    StringRef KeyValue = KeyString->getValue(KeyStorage);
+    auto *Value =
+        dyn_cast_or_null<llvm::yaml::ScalarNode>(NextKeyValue.getValue());
+    if (!Value)
+      continue;
+
+    if (KeyValue == "processId") {
+      auto *Value =
+          dyn_cast_or_null<llvm::yaml::ScalarNode>(NextKeyValue.getValue());
+      if (!Value)
+        return ParseFailure();
+      long long Val;
+      if (llvm::getAsSignedInteger(Value->getValue(KeyStorage), 0, Val))
+        return ParseFailure();
+      Result.processId = Val;
+    } else if (KeyValue == "rootPath") {
+      Result.rootPath = Value->getValue(KeyStorage);
+    } else if (KeyValue == "rootUri") {
+      Result.rootUri = URI::parse(Value);
+    } else if (KeyValue == "initializationOptions") {
+      // Not used
+    } else if (KeyValue == "capabilities") {
+      // Not used
+    } else if (KeyValue == "trace") {
+      Result.trace = getTraceLevel(Value->getValue(KeyStorage), Logger);
+    } else {
+      logIgnoredField(KeyValue, Logger);
+    }
+  }
+  return Result;
+}
+
 llvm::Optional<DidOpenTextDocumentParams>
-DidOpenTextDocumentParams::parse(llvm::yaml::MappingNode *Params) {
+DidOpenTextDocumentParams::parse(llvm::yaml::MappingNode *Params,
+                                 clangd::Logger &Logger) {
   DidOpenTextDocumentParams Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -253,19 +367,25 @@
 
     llvm::SmallString<10> Storage;
     if (KeyValue == "textDocument") {
-      auto Parsed = TextDocumentItem::parse(Value);
+      auto Parsed = TextDocumentItem::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.textDocument = std::move(*Parsed);
+    } else if (KeyValue == "metadata") {
+      auto Parsed = Metadata::parse(Value, Logger);
+      if (!Parsed)
+        return llvm::None;
+      Result.metadata = std::move(*Parsed);
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
 llvm::Optional<DidCloseTextDocumentParams>
-DidCloseTextDocumentParams::parse(llvm::yaml::MappingNode *Params) {
+DidCloseTextDocumentParams::parse(llvm::yaml::MappingNode *Params,
+                                  clangd::Logger &Logger) {
   DidCloseTextDocumentParams Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -280,19 +400,20 @@
       auto *Map = dyn_cast<llvm::yaml::MappingNode>(Value);
       if (!Map)
         return llvm::None;
-      auto Parsed = TextDocumentIdentifier::parse(Map);
+      auto Parsed = TextDocumentIdentifier::parse(Map, Logger);
       if (!Parsed)
         return llvm::None;
       Result.textDocument = std::move(*Parsed);
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
 llvm::Optional<DidChangeTextDocumentParams>
-DidChangeTextDocumentParams::parse(llvm::yaml::MappingNode *Params) {
+DidChangeTextDocumentParams::parse(llvm::yaml::MappingNode *Params,
+                                   clangd::Logger &Logger) {
   DidChangeTextDocumentParams Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -308,7 +429,7 @@
       auto *Map = dyn_cast<llvm::yaml::MappingNode>(Value);
       if (!Map)
         return llvm::None;
-      auto Parsed = TextDocumentIdentifier::parse(Map);
+      auto Parsed = TextDocumentIdentifier::parse(Map, Logger);
       if (!Parsed)
         return llvm::None;
       Result.textDocument = std::move(*Parsed);
@@ -320,20 +441,99 @@
         auto *I = dyn_cast<llvm::yaml::MappingNode>(&Item);
         if (!I)
           return llvm::None;
-        auto Parsed = TextDocumentContentChangeEvent::parse(I);
+        auto Parsed = TextDocumentContentChangeEvent::parse(I, Logger);
         if (!Parsed)
           return llvm::None;
         Result.contentChanges.push_back(std::move(*Parsed));
       }
     } else {
+      logIgnoredField(KeyValue, Logger);
+    }
+  }
+  return Result;
+}
+
+llvm::Optional<FileEvent> FileEvent::parse(llvm::yaml::MappingNode *Params,
+                                           clangd::Logger &Logger) {
+  llvm::Optional<FileEvent> Result = FileEvent();
+  for (auto &NextKeyValue : *Params) {
+    // We have to consume the whole MappingNode because it doesn't support
+    // skipping and we want to be able to parse further valid events.
+    if (!Result)
+      continue;
+
+    auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
+    if (!KeyString) {
+      Result.reset();
+      continue;
+    }
+
+    llvm::SmallString<10> KeyStorage;
+    StringRef KeyValue = KeyString->getValue(KeyStorage);
+    auto *Value =
+        dyn_cast_or_null<llvm::yaml::ScalarNode>(NextKeyValue.getValue());
+    if (!Value) {
+      Result.reset();
+      continue;
+    }
+    llvm::SmallString<10> Storage;
+    if (KeyValue == "uri") {
+      Result->uri = URI::parse(Value);
+    } else if (KeyValue == "type") {
+      long long Val;
+      if (llvm::getAsSignedInteger(Value->getValue(Storage), 0, Val)) {
+        Result.reset();
+        continue;
+      }
+      Result->type = static_cast<FileChangeType>(Val);
+      if (Result->type < FileChangeType::Created ||
+          Result->type > FileChangeType::Deleted)
+        Result.reset();
+    } else {
+      logIgnoredField(KeyValue, Logger);
+    }
+  }
+  return Result;
+}
+
+llvm::Optional<DidChangeWatchedFilesParams>
+DidChangeWatchedFilesParams::parse(llvm::yaml::MappingNode *Params,
+                                   clangd::Logger &Logger) {
+  DidChangeWatchedFilesParams Result;
+  for (auto &NextKeyValue : *Params) {
+    auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
+    if (!KeyString)
       return llvm::None;
+
+    llvm::SmallString<10> KeyStorage;
+    StringRef KeyValue = KeyString->getValue(KeyStorage);
+    auto *Value = NextKeyValue.getValue();
+
+    llvm::SmallString<10> Storage;
+    if (KeyValue == "changes") {
+      auto *Seq = dyn_cast<llvm::yaml::SequenceNode>(Value);
+      if (!Seq)
+        return llvm::None;
+      for (auto &Item : *Seq) {
+        auto *I = dyn_cast<llvm::yaml::MappingNode>(&Item);
+        if (!I)
+          return llvm::None;
+        auto Parsed = FileEvent::parse(I, Logger);
+        if (Parsed)
+          Result.changes.push_back(std::move(*Parsed));
+        else
+          Logger.log("Failed to decode a FileEvent.\n");
+      }
+    } else {
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
 llvm::Optional<TextDocumentContentChangeEvent>
-TextDocumentContentChangeEvent::parse(llvm::yaml::MappingNode *Params) {
+TextDocumentContentChangeEvent::parse(llvm::yaml::MappingNode *Params,
+                                      clangd::Logger &Logger) {
   TextDocumentContentChangeEvent Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -351,14 +551,15 @@
     if (KeyValue == "text") {
       Result.text = Value->getValue(Storage);
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
 llvm::Optional<FormattingOptions>
-FormattingOptions::parse(llvm::yaml::MappingNode *Params) {
+FormattingOptions::parse(llvm::yaml::MappingNode *Params,
+                         clangd::Logger &Logger) {
   FormattingOptions Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -391,7 +592,7 @@
       }
       Result.insertSpaces = Val;
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
@@ -405,7 +606,8 @@
 }
 
 llvm::Optional<DocumentRangeFormattingParams>
-DocumentRangeFormattingParams::parse(llvm::yaml::MappingNode *Params) {
+DocumentRangeFormattingParams::parse(llvm::yaml::MappingNode *Params,
+                                     clangd::Logger &Logger) {
   DocumentRangeFormattingParams Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -421,29 +623,30 @@
 
     llvm::SmallString<10> Storage;
     if (KeyValue == "textDocument") {
-      auto Parsed = TextDocumentIdentifier::parse(Value);
+      auto Parsed = TextDocumentIdentifier::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.textDocument = std::move(*Parsed);
     } else if (KeyValue == "range") {
-      auto Parsed = Range::parse(Value);
+      auto Parsed = Range::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.range = std::move(*Parsed);
     } else if (KeyValue == "options") {
-      auto Parsed = FormattingOptions::parse(Value);
+      auto Parsed = FormattingOptions::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.options = std::move(*Parsed);
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
 llvm::Optional<DocumentOnTypeFormattingParams>
-DocumentOnTypeFormattingParams::parse(llvm::yaml::MappingNode *Params) {
+DocumentOnTypeFormattingParams::parse(llvm::yaml::MappingNode *Params,
+                                      clangd::Logger &Logger) {
   DocumentOnTypeFormattingParams Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -468,29 +671,30 @@
     if (!Value)
       return llvm::None;
     if (KeyValue == "textDocument") {
-      auto Parsed = TextDocumentIdentifier::parse(Value);
+      auto Parsed = TextDocumentIdentifier::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.textDocument = std::move(*Parsed);
     } else if (KeyValue == "position") {
-      auto Parsed = Position::parse(Value);
+      auto Parsed = Position::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.position = std::move(*Parsed);
     } else if (KeyValue == "options") {
-      auto Parsed = FormattingOptions::parse(Value);
+      auto Parsed = FormattingOptions::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.options = std::move(*Parsed);
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
 llvm::Optional<DocumentFormattingParams>
-DocumentFormattingParams::parse(llvm::yaml::MappingNode *Params) {
+DocumentFormattingParams::parse(llvm::yaml::MappingNode *Params,
+                                clangd::Logger &Logger) {
   DocumentFormattingParams Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -506,23 +710,24 @@
 
     llvm::SmallString<10> Storage;
     if (KeyValue == "textDocument") {
-      auto Parsed = TextDocumentIdentifier::parse(Value);
+      auto Parsed = TextDocumentIdentifier::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.textDocument = std::move(*Parsed);
     } else if (KeyValue == "options") {
-      auto Parsed = FormattingOptions::parse(Value);
+      auto Parsed = FormattingOptions::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.options = std::move(*Parsed);
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
-llvm::Optional<Diagnostic> Diagnostic::parse(llvm::yaml::MappingNode *Params) {
+llvm::Optional<Diagnostic> Diagnostic::parse(llvm::yaml::MappingNode *Params,
+                                             clangd::Logger &Logger) {
   Diagnostic Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -538,7 +743,7 @@
           dyn_cast_or_null<llvm::yaml::MappingNode>(NextKeyValue.getValue());
       if (!Value)
         return llvm::None;
-      auto Parsed = Range::parse(Value);
+      auto Parsed = Range::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.range = std::move(*Parsed);
@@ -551,6 +756,10 @@
       if (llvm::getAsSignedInteger(Value->getValue(Storage), 0, Val))
         return llvm::None;
       Result.severity = Val;
+    } else if (KeyValue == "code") {
+      // Not currently used
+    } else if (KeyValue == "source") {
+      // Not currently used
     } else if (KeyValue == "message") {
       auto *Value =
           dyn_cast_or_null<llvm::yaml::ScalarNode>(NextKeyValue.getValue());
@@ -558,14 +767,15 @@
         return llvm::None;
       Result.message = Value->getValue(Storage);
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
 llvm::Optional<CodeActionContext>
-CodeActionContext::parse(llvm::yaml::MappingNode *Params) {
+CodeActionContext::parse(llvm::yaml::MappingNode *Params,
+                         clangd::Logger &Logger) {
   CodeActionContext Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -585,20 +795,21 @@
         auto *I = dyn_cast<llvm::yaml::MappingNode>(&Item);
         if (!I)
           return llvm::None;
-        auto Parsed = Diagnostic::parse(I);
+        auto Parsed = Diagnostic::parse(I, Logger);
         if (!Parsed)
           return llvm::None;
         Result.diagnostics.push_back(std::move(*Parsed));
       }
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
 llvm::Optional<CodeActionParams>
-CodeActionParams::parse(llvm::yaml::MappingNode *Params) {
+CodeActionParams::parse(llvm::yaml::MappingNode *Params,
+                        clangd::Logger &Logger) {
   CodeActionParams Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -614,29 +825,30 @@
 
     llvm::SmallString<10> Storage;
     if (KeyValue == "textDocument") {
-      auto Parsed = TextDocumentIdentifier::parse(Value);
+      auto Parsed = TextDocumentIdentifier::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.textDocument = std::move(*Parsed);
     } else if (KeyValue == "range") {
-      auto Parsed = Range::parse(Value);
+      auto Parsed = Range::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.range = std::move(*Parsed);
     } else if (KeyValue == "context") {
-      auto Parsed = CodeActionContext::parse(Value);
+      auto Parsed = CodeActionContext::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.context = std::move(*Parsed);
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
 llvm::Optional<TextDocumentPositionParams>
-TextDocumentPositionParams::parse(llvm::yaml::MappingNode *Params) {
+TextDocumentPositionParams::parse(llvm::yaml::MappingNode *Params,
+                                  clangd::Logger &Logger) {
   TextDocumentPositionParams Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -652,17 +864,17 @@
 
     llvm::SmallString<10> Storage;
     if (KeyValue == "textDocument") {
-      auto Parsed = TextDocumentIdentifier::parse(Value);
+      auto Parsed = TextDocumentIdentifier::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.textDocument = std::move(*Parsed);
     } else if (KeyValue == "position") {
-      auto Parsed = Position::parse(Value);
+      auto Parsed = Position::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.position = std::move(*Parsed);
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
@@ -687,8 +899,8 @@
   if (!CI.insertText.empty())
     Os << R"("insertText":")" << llvm::yaml::escape(CI.insertText) << R"(",)";
   if (CI.insertTextFormat != InsertTextFormat::Missing) {
-    Os << R"("insertTextFormat":")" << static_cast<int>(CI.insertTextFormat)
-       << R"(",)";
+    Os << R"("insertTextFormat":)" << static_cast<int>(CI.insertTextFormat)
+       << R"(,)";
   }
   if (CI.textEdit)
     Os << R"("textEdit":)" << TextEdit::unparse(*CI.textEdit) << ',';
@@ -706,3 +918,58 @@
   Result.back() = '}';
   return Result;
 }
+
+std::string ParameterInformation::unparse(const ParameterInformation &PI) {
+  std::string Result = "{";
+  llvm::raw_string_ostream Os(Result);
+  assert(!PI.label.empty() && "parameter information label is required");
+  Os << R"("label":")" << llvm::yaml::escape(PI.label) << '\"';
+  if (!PI.documentation.empty())
+    Os << R"(,"documentation":")" << llvm::yaml::escape(PI.documentation)
+       << '\"';
+  Os << '}';
+  Os.flush();
+  return Result;
+}
+
+std::string SignatureInformation::unparse(const SignatureInformation &SI) {
+  std::string Result = "{";
+  llvm::raw_string_ostream Os(Result);
+  assert(!SI.label.empty() && "signature information label is required");
+  Os << R"("label":")" << llvm::yaml::escape(SI.label) << '\"';
+  if (!SI.documentation.empty())
+    Os << R"(,"documentation":")" << llvm::yaml::escape(SI.documentation)
+       << '\"';
+  Os << R"(,"parameters":[)";
+  for (const auto &Parameter : SI.parameters) {
+    Os << ParameterInformation::unparse(Parameter) << ',';
+  }
+  Os.flush();
+  if (SI.parameters.empty())
+    Result.push_back(']');
+  else
+    Result.back() = ']'; // Replace the last `,` with an `]`.
+  Result.push_back('}');
+  return Result;
+}
+
+std::string SignatureHelp::unparse(const SignatureHelp &SH) {
+  std::string Result = "{";
+  llvm::raw_string_ostream Os(Result);
+  assert(SH.activeSignature >= 0 &&
+         "Unexpected negative value for number of active signatures.");
+  assert(SH.activeParameter >= 0 &&
+         "Unexpected negative value for active parameter index");
+  Os << R"("activeSignature":)" << SH.activeSignature
+     << R"(,"activeParameter":)" << SH.activeParameter << R"(,"signatures":[)";
+  for (const auto &Signature : SH.signatures) {
+    Os << SignatureInformation::unparse(Signature) << ',';
+  }
+  Os.flush();
+  if (SH.signatures.empty())
+    Result.push_back(']');
+  else
+    Result.back() = ']'; // Replace the last `,` with an `]`.
+  Result.push_back('}');
+  return Result;
+}
diff --git a/clangd/Protocol.h b/clangd/Protocol.h
index 8fd2ccc..48a5875 100644
--- a/clangd/Protocol.h
+++ b/clangd/Protocol.h
@@ -29,6 +29,8 @@
 namespace clang {
 namespace clangd {
 
+class Logger;
+
 struct URI {
   std::string uri;
   std::string file;
@@ -38,6 +40,18 @@
 
   static URI parse(llvm::yaml::ScalarNode *Param);
   static std::string unparse(const URI &U);
+
+  friend bool operator==(const URI &LHS, const URI &RHS) {
+    return LHS.uri == RHS.uri;
+  }
+
+  friend bool operator!=(const URI &LHS, const URI &RHS) {
+    return !(LHS == RHS);
+  }
+
+  friend bool operator<(const URI &LHS, const URI &RHS) {
+    return LHS.uri < RHS.uri;
+  }
 };
 
 struct TextDocumentIdentifier {
@@ -45,7 +59,7 @@
   URI uri;
 
   static llvm::Optional<TextDocumentIdentifier>
-  parse(llvm::yaml::MappingNode *Params);
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
 };
 
 struct Position {
@@ -64,7 +78,8 @@
            std::tie(RHS.line, RHS.character);
   }
 
-  static llvm::Optional<Position> parse(llvm::yaml::MappingNode *Params);
+  static llvm::Optional<Position> parse(llvm::yaml::MappingNode *Params,
+                                        clangd::Logger &Logger);
   static std::string unparse(const Position &P);
 };
 
@@ -82,10 +97,38 @@
     return std::tie(LHS.start, LHS.end) < std::tie(RHS.start, RHS.end);
   }
 
-  static llvm::Optional<Range> parse(llvm::yaml::MappingNode *Params);
+  static llvm::Optional<Range> parse(llvm::yaml::MappingNode *Params,
+                                     clangd::Logger &Logger);
   static std::string unparse(const Range &P);
 };
 
+struct Location {
+  /// The text document's URI.
+  URI uri;
+  Range range;
+
+  friend bool operator==(const Location &LHS, const Location &RHS) {
+    return LHS.uri == RHS.uri && LHS.range == RHS.range;
+  }
+
+  friend bool operator!=(const Location &LHS, const Location &RHS) {
+    return !(LHS == RHS);
+  }
+
+  friend bool operator<(const Location &LHS, const Location &RHS) {
+    return std::tie(LHS.uri, LHS.range) < std::tie(RHS.uri, RHS.range);
+  }
+
+  static std::string unparse(const Location &P);
+};
+
+struct Metadata {
+  std::vector<std::string> extraFlags;
+
+  static llvm::Optional<Metadata> parse(llvm::yaml::MappingNode *Params,
+                                        clangd::Logger &Logger);
+};
+
 struct TextEdit {
   /// The range of the text document to be manipulated. To insert
   /// text into a document create a range where start === end.
@@ -95,7 +138,8 @@
   /// empty string.
   std::string newText;
 
-  static llvm::Optional<TextEdit> parse(llvm::yaml::MappingNode *Params);
+  static llvm::Optional<TextEdit> parse(llvm::yaml::MappingNode *Params,
+                                        clangd::Logger &Logger);
   static std::string unparse(const TextEdit &P);
 };
 
@@ -112,16 +156,64 @@
   /// The content of the opened text document.
   std::string text;
 
-  static llvm::Optional<TextDocumentItem>
-  parse(llvm::yaml::MappingNode *Params);
+  static llvm::Optional<TextDocumentItem> parse(llvm::yaml::MappingNode *Params,
+                                                clangd::Logger &Logger);
+};
+
+enum class TraceLevel {
+  Off = 0,
+  Messages = 1,
+  Verbose = 2,
+};
+
+struct NoParams {
+  static llvm::Optional<NoParams> parse(llvm::yaml::MappingNode *Params,
+                                        Logger &Logger) {
+    return NoParams{};
+  }
+};
+using ShutdownParams = NoParams;
+
+struct InitializeParams {
+  /// The process Id of the parent process that started
+  /// the server. Is null if the process has not been started by another
+  /// process. If the parent process is not alive then the server should exit
+  /// (see exit notification) its process.
+  llvm::Optional<int> processId;
+
+  /// The rootPath of the workspace. Is null
+  /// if no folder is open.
+  ///
+  /// @deprecated in favour of rootUri.
+  llvm::Optional<std::string> rootPath;
+
+  /// The rootUri of the workspace. Is null if no
+  /// folder is open. If both `rootPath` and `rootUri` are set
+  /// `rootUri` wins.
+  llvm::Optional<URI> rootUri;
+
+  // User provided initialization options.
+  // initializationOptions?: any;
+
+  /// The capabilities provided by the client (editor or tool)
+  /// Note: Not currently used by clangd
+  // ClientCapabilities capabilities;
+
+  /// The initial trace setting. If omitted trace is disabled ('off').
+  llvm::Optional<TraceLevel> trace;
+  static llvm::Optional<InitializeParams> parse(llvm::yaml::MappingNode *Params,
+                                                clangd::Logger &Logger);
 };
 
 struct DidOpenTextDocumentParams {
   /// The document that was opened.
   TextDocumentItem textDocument;
 
+  /// Extension storing per-file metadata, such as compilation flags.
+  llvm::Optional<Metadata> metadata;
+
   static llvm::Optional<DidOpenTextDocumentParams>
-  parse(llvm::yaml::MappingNode *Params);
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
 };
 
 struct DidCloseTextDocumentParams {
@@ -129,7 +221,7 @@
   TextDocumentIdentifier textDocument;
 
   static llvm::Optional<DidCloseTextDocumentParams>
-  parse(llvm::yaml::MappingNode *Params);
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
 };
 
 struct TextDocumentContentChangeEvent {
@@ -137,7 +229,7 @@
   std::string text;
 
   static llvm::Optional<TextDocumentContentChangeEvent>
-  parse(llvm::yaml::MappingNode *Params);
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
 };
 
 struct DidChangeTextDocumentParams {
@@ -150,7 +242,34 @@
   std::vector<TextDocumentContentChangeEvent> contentChanges;
 
   static llvm::Optional<DidChangeTextDocumentParams>
-  parse(llvm::yaml::MappingNode *Params);
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
+};
+
+enum class FileChangeType {
+  /// The file got created.
+  Created = 1,
+  /// The file got changed.
+  Changed = 2,
+  /// The file got deleted.
+  Deleted = 3
+};
+
+struct FileEvent {
+  /// The file's URI.
+  URI uri;
+  /// The change type.
+  FileChangeType type;
+
+  static llvm::Optional<FileEvent> parse(llvm::yaml::MappingNode *Params,
+                                         clangd::Logger &Logger);
+};
+
+struct DidChangeWatchedFilesParams {
+  /// The actual file events.
+  std::vector<FileEvent> changes;
+
+  static llvm::Optional<DidChangeWatchedFilesParams>
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
 };
 
 struct FormattingOptions {
@@ -161,7 +280,7 @@
   bool insertSpaces;
 
   static llvm::Optional<FormattingOptions>
-  parse(llvm::yaml::MappingNode *Params);
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
   static std::string unparse(const FormattingOptions &P);
 };
 
@@ -176,7 +295,7 @@
   FormattingOptions options;
 
   static llvm::Optional<DocumentRangeFormattingParams>
-  parse(llvm::yaml::MappingNode *Params);
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
 };
 
 struct DocumentOnTypeFormattingParams {
@@ -193,7 +312,7 @@
   FormattingOptions options;
 
   static llvm::Optional<DocumentOnTypeFormattingParams>
-  parse(llvm::yaml::MappingNode *Params);
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
 };
 
 struct DocumentFormattingParams {
@@ -204,7 +323,7 @@
   FormattingOptions options;
 
   static llvm::Optional<DocumentFormattingParams>
-  parse(llvm::yaml::MappingNode *Params);
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
 };
 
 struct Diagnostic {
@@ -215,6 +334,15 @@
   /// client to interpret diagnostics as error, warning, info or hint.
   int severity;
 
+  /// The diagnostic's code. Can be omitted.
+  /// Note: Not currently used by clangd
+  // std::string code;
+
+  /// A human-readable string describing the source of this
+  /// diagnostic, e.g. 'typescript' or 'super lint'.
+  /// Note: Not currently used by clangd
+  // std::string source;
+
   /// The diagnostic's message.
   std::string message;
 
@@ -227,7 +355,8 @@
            std::tie(RHS.range, RHS.severity, RHS.message);
   }
 
-  static llvm::Optional<Diagnostic> parse(llvm::yaml::MappingNode *Params);
+  static llvm::Optional<Diagnostic> parse(llvm::yaml::MappingNode *Params,
+                                          clangd::Logger &Logger);
 };
 
 struct CodeActionContext {
@@ -235,7 +364,7 @@
   std::vector<Diagnostic> diagnostics;
 
   static llvm::Optional<CodeActionContext>
-  parse(llvm::yaml::MappingNode *Params);
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
 };
 
 struct CodeActionParams {
@@ -248,8 +377,8 @@
   /// Context carrying additional information.
   CodeActionContext context;
 
-  static llvm::Optional<CodeActionParams>
-  parse(llvm::yaml::MappingNode *Params);
+  static llvm::Optional<CodeActionParams> parse(llvm::yaml::MappingNode *Params,
+                                                clangd::Logger &Logger);
 };
 
 struct TextDocumentPositionParams {
@@ -260,7 +389,7 @@
   Position position;
 
   static llvm::Optional<TextDocumentPositionParams>
-  parse(llvm::yaml::MappingNode *Params);
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
 };
 
 /// The kind of a completion entry.
@@ -359,6 +488,48 @@
   static std::string unparse(const CompletionItem &P);
 };
 
+/// A single parameter of a particular signature.
+struct ParameterInformation {
+
+  /// The label of this parameter. Mandatory.
+  std::string label;
+
+  /// The documentation of this parameter. Optional.
+  std::string documentation;
+
+  static std::string unparse(const ParameterInformation &);
+};
+
+/// Represents the signature of something callable.
+struct SignatureInformation {
+
+  /// The label of this signature. Mandatory.
+  std::string label;
+
+  /// The documentation of this signature. Optional.
+  std::string documentation;
+
+  /// The parameters of this signature.
+  std::vector<ParameterInformation> parameters;
+
+  static std::string unparse(const SignatureInformation &);
+};
+
+/// Represents the signature of a callable.
+struct SignatureHelp {
+
+  /// The resulting signatures.
+  std::vector<SignatureInformation> signatures;
+
+  /// The active signature.
+  int activeSignature = 0;
+
+  /// The active parameter of the active signature.
+  int activeParameter = 0;
+
+  static std::string unparse(const SignatureHelp &);
+};
+
 } // namespace clangd
 } // namespace clang
 
diff --git a/clangd/ProtocolHandlers.cpp b/clangd/ProtocolHandlers.cpp
index 264ef33..7891e5b 100644
--- a/clangd/ProtocolHandlers.cpp
+++ b/clangd/ProtocolHandlers.cpp
@@ -11,212 +11,60 @@
 #include "ClangdLSPServer.h"
 #include "ClangdServer.h"
 #include "DraftStore.h"
+
 using namespace clang;
-using namespace clangd;
+using namespace clang::clangd;
 
 namespace {
 
-struct InitializeHandler : Handler {
-  InitializeHandler(JSONOutput &Output, ProtocolCallbacks &Callbacks)
-      : Handler(Output), Callbacks(Callbacks) {}
-
-  void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override {
-    Callbacks.onInitialize(ID, Output);
+// Helper for attaching ProtocolCallbacks methods to a JSONRPCDispatcher.
+// Invoke like: Registerer("foo", &ProtocolCallbacks::onFoo)
+// onFoo should be: void onFoo(Ctx &C, FooParams &Params)
+// FooParams should have a static factory method: parse(yaml::MappingNode*).
+struct HandlerRegisterer {
+  template <typename Param>
+  void operator()(StringRef Method,
+                  void (ProtocolCallbacks::*Handler)(RequestContext, Param)) {
+    // Capture pointers by value, as the lambda will outlive this object.
+    auto *Out = this->Out;
+    auto *Callbacks = this->Callbacks;
+    Dispatcher.registerHandler(
+        Method, [=](RequestContext C, llvm::yaml::MappingNode *RawParams) {
+          if (auto P = std::decay<Param>::type::parse(RawParams, *Out)) {
+            (Callbacks->*Handler)(std::move(C), *P);
+          } else {
+            Out->log("Failed to decode " + Method + " request.\n");
+          }
+        });
   }
 
-private:
-  ProtocolCallbacks &Callbacks;
-};
-
-struct ShutdownHandler : Handler {
-  ShutdownHandler(JSONOutput &Output, ProtocolCallbacks &Callbacks)
-      : Handler(Output), Callbacks(Callbacks) {}
-
-  void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override {
-    Callbacks.onShutdown(Output);
-  }
-
-private:
-  ProtocolCallbacks &Callbacks;
-};
-
-struct TextDocumentDidOpenHandler : Handler {
-  TextDocumentDidOpenHandler(JSONOutput &Output, ProtocolCallbacks &Callbacks)
-      : Handler(Output), Callbacks(Callbacks) {}
-
-  void handleNotification(llvm::yaml::MappingNode *Params) override {
-    auto DOTDP = DidOpenTextDocumentParams::parse(Params);
-    if (!DOTDP) {
-      Output.log("Failed to decode DidOpenTextDocumentParams!\n");
-      return;
-    }
-    Callbacks.onDocumentDidOpen(*DOTDP, Output);
-  }
-
-private:
-  ProtocolCallbacks &Callbacks;
-};
-
-struct TextDocumentDidChangeHandler : Handler {
-  TextDocumentDidChangeHandler(JSONOutput &Output, ProtocolCallbacks &Callbacks)
-      : Handler(Output), Callbacks(Callbacks) {}
-
-  void handleNotification(llvm::yaml::MappingNode *Params) override {
-    auto DCTDP = DidChangeTextDocumentParams::parse(Params);
-    if (!DCTDP || DCTDP->contentChanges.size() != 1) {
-      Output.log("Failed to decode DidChangeTextDocumentParams!\n");
-      return;
-    }
-
-    Callbacks.onDocumentDidChange(*DCTDP, Output);
-  }
-
-private:
-  ProtocolCallbacks &Callbacks;
-};
-
-struct TextDocumentDidCloseHandler : Handler {
-  TextDocumentDidCloseHandler(JSONOutput &Output, ProtocolCallbacks &Callbacks)
-      : Handler(Output), Callbacks(Callbacks) {}
-
-  void handleNotification(llvm::yaml::MappingNode *Params) override {
-    auto DCTDP = DidCloseTextDocumentParams::parse(Params);
-    if (!DCTDP) {
-      Output.log("Failed to decode DidCloseTextDocumentParams!\n");
-      return;
-    }
-
-    Callbacks.onDocumentDidClose(*DCTDP, Output);
-  }
-
-private:
-  ProtocolCallbacks &Callbacks;
-};
-
-struct TextDocumentOnTypeFormattingHandler : Handler {
-  TextDocumentOnTypeFormattingHandler(JSONOutput &Output,
-                                      ProtocolCallbacks &Callbacks)
-      : Handler(Output), Callbacks(Callbacks) {}
-
-  void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override {
-    auto DOTFP = DocumentOnTypeFormattingParams::parse(Params);
-    if (!DOTFP) {
-      Output.log("Failed to decode DocumentOnTypeFormattingParams!\n");
-      return;
-    }
-
-    Callbacks.onDocumentOnTypeFormatting(*DOTFP, ID, Output);
-  }
-
-private:
-  ProtocolCallbacks &Callbacks;
-};
-
-struct TextDocumentRangeFormattingHandler : Handler {
-  TextDocumentRangeFormattingHandler(JSONOutput &Output,
-                                     ProtocolCallbacks &Callbacks)
-      : Handler(Output), Callbacks(Callbacks) {}
-
-  void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override {
-    auto DRFP = DocumentRangeFormattingParams::parse(Params);
-    if (!DRFP) {
-      Output.log("Failed to decode DocumentRangeFormattingParams!\n");
-      return;
-    }
-
-    Callbacks.onDocumentRangeFormatting(*DRFP, ID, Output);
-  }
-
-private:
-  ProtocolCallbacks &Callbacks;
-};
-
-struct TextDocumentFormattingHandler : Handler {
-  TextDocumentFormattingHandler(JSONOutput &Output,
-                                ProtocolCallbacks &Callbacks)
-      : Handler(Output), Callbacks(Callbacks) {}
-
-  void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override {
-    auto DFP = DocumentFormattingParams::parse(Params);
-    if (!DFP) {
-      Output.log("Failed to decode DocumentFormattingParams!\n");
-      return;
-    }
-
-    Callbacks.onDocumentFormatting(*DFP, ID, Output);
-  }
-
-private:
-  ProtocolCallbacks &Callbacks;
-};
-
-struct CodeActionHandler : Handler {
-  CodeActionHandler(JSONOutput &Output, ProtocolCallbacks &Callbacks)
-      : Handler(Output), Callbacks(Callbacks) {}
-
-  void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override {
-    auto CAP = CodeActionParams::parse(Params);
-    if (!CAP) {
-      Output.log("Failed to decode CodeActionParams!\n");
-      return;
-    }
-
-    Callbacks.onCodeAction(*CAP, ID, Output);
-  }
-
-private:
-  ProtocolCallbacks &Callbacks;
-};
-
-struct CompletionHandler : Handler {
-  CompletionHandler(JSONOutput &Output, ProtocolCallbacks &Callbacks)
-      : Handler(Output), Callbacks(Callbacks) {}
-
-  void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override {
-    auto TDPP = TextDocumentPositionParams::parse(Params);
-    if (!TDPP) {
-      Output.log("Failed to decode TextDocumentPositionParams!\n");
-      return;
-    }
-
-    Callbacks.onCompletion(*TDPP, ID, Output);
-  }
-
-private:
-  ProtocolCallbacks &Callbacks;
+  JSONRPCDispatcher &Dispatcher;
+  JSONOutput *Out;
+  ProtocolCallbacks *Callbacks;
 };
 
 } // namespace
 
-void clangd::regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher,
-                                     JSONOutput &Out,
-                                     ProtocolCallbacks &Callbacks) {
-  Dispatcher.registerHandler(
-      "initialize", llvm::make_unique<InitializeHandler>(Out, Callbacks));
-  Dispatcher.registerHandler(
-      "shutdown", llvm::make_unique<ShutdownHandler>(Out, Callbacks));
-  Dispatcher.registerHandler(
-      "textDocument/didOpen",
-      llvm::make_unique<TextDocumentDidOpenHandler>(Out, Callbacks));
-  Dispatcher.registerHandler(
-      "textDocument/didClose",
-      llvm::make_unique<TextDocumentDidCloseHandler>(Out, Callbacks));
-  Dispatcher.registerHandler(
-      "textDocument/didChange",
-      llvm::make_unique<TextDocumentDidChangeHandler>(Out, Callbacks));
-  Dispatcher.registerHandler(
-      "textDocument/rangeFormatting",
-      llvm::make_unique<TextDocumentRangeFormattingHandler>(Out, Callbacks));
-  Dispatcher.registerHandler(
-      "textDocument/onTypeFormatting",
-      llvm::make_unique<TextDocumentOnTypeFormattingHandler>(Out, Callbacks));
-  Dispatcher.registerHandler(
-      "textDocument/formatting",
-      llvm::make_unique<TextDocumentFormattingHandler>(Out, Callbacks));
-  Dispatcher.registerHandler(
-      "textDocument/codeAction",
-      llvm::make_unique<CodeActionHandler>(Out, Callbacks));
-  Dispatcher.registerHandler(
-      "textDocument/completion",
-      llvm::make_unique<CompletionHandler>(Out, Callbacks));
+void clangd::registerCallbackHandlers(JSONRPCDispatcher &Dispatcher,
+                                      JSONOutput &Out,
+                                      ProtocolCallbacks &Callbacks) {
+  HandlerRegisterer Register{Dispatcher, &Out, &Callbacks};
+
+  Register("initialize", &ProtocolCallbacks::onInitialize);
+  Register("shutdown", &ProtocolCallbacks::onShutdown);
+  Register("textDocument/didOpen", &ProtocolCallbacks::onDocumentDidOpen);
+  Register("textDocument/didClose", &ProtocolCallbacks::onDocumentDidClose);
+  Register("textDocument/didChange", &ProtocolCallbacks::onDocumentDidChange);
+  Register("textDocument/rangeFormatting",
+           &ProtocolCallbacks::onDocumentRangeFormatting);
+  Register("textDocument/onTypeFormatting",
+           &ProtocolCallbacks::onDocumentOnTypeFormatting);
+  Register("textDocument/formatting", &ProtocolCallbacks::onDocumentFormatting);
+  Register("textDocument/codeAction", &ProtocolCallbacks::onCodeAction);
+  Register("textDocument/completion", &ProtocolCallbacks::onCompletion);
+  Register("textDocument/signatureHelp", &ProtocolCallbacks::onSignatureHelp);
+  Register("textDocument/definition", &ProtocolCallbacks::onGoToDefinition);
+  Register("textDocument/switchSourceHeader",
+           &ProtocolCallbacks::onSwitchSourceHeader);
+  Register("workspace/didChangeWatchedFiles", &ProtocolCallbacks::onFileEvent);
 }
diff --git a/clangd/ProtocolHandlers.h b/clangd/ProtocolHandlers.h
index 2fb3db8..ac819ba 100644
--- a/clangd/ProtocolHandlers.h
+++ b/clangd/ProtocolHandlers.h
@@ -7,8 +7,11 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file contains the actions performed when the server gets a specific
-// request.
+// ProtocolHandlers translates incoming JSON requests from JSONRPCDispatcher
+// into method calls on ClangLSPServer.
+//
+// Currently it parses requests into objects, but the ClangLSPServer is
+// responsible for producing JSON responses. We should move that here, too.
 //
 //===----------------------------------------------------------------------===//
 
@@ -23,33 +26,35 @@
 namespace clang {
 namespace clangd {
 
+// The interface implemented by ClangLSPServer to handle incoming requests.
 class ProtocolCallbacks {
 public:
+  using Ctx = RequestContext;
   virtual ~ProtocolCallbacks() = default;
 
-  virtual void onInitialize(StringRef ID, JSONOutput &Out) = 0;
-  virtual void onShutdown(JSONOutput &Out) = 0;
-  virtual void onDocumentDidOpen(DidOpenTextDocumentParams Params,
-                                 JSONOutput &Out) = 0;
-  virtual void onDocumentDidChange(DidChangeTextDocumentParams Params,
-                                   JSONOutput &Out) = 0;
-
-  virtual void onDocumentDidClose(DidCloseTextDocumentParams Params,
-                                  JSONOutput &Out) = 0;
-  virtual void onDocumentFormatting(DocumentFormattingParams Params,
-                                    StringRef ID, JSONOutput &Out) = 0;
-  virtual void onDocumentOnTypeFormatting(DocumentOnTypeFormattingParams Params,
-                                          StringRef ID, JSONOutput &Out) = 0;
-  virtual void onDocumentRangeFormatting(DocumentRangeFormattingParams Params,
-                                         StringRef ID, JSONOutput &Out) = 0;
-  virtual void onCodeAction(CodeActionParams Params, StringRef ID,
-                            JSONOutput &Out) = 0;
-  virtual void onCompletion(TextDocumentPositionParams Params, StringRef ID,
-                            JSONOutput &Out) = 0;
+  virtual void onInitialize(Ctx C, InitializeParams &Params) = 0;
+  virtual void onShutdown(Ctx C, ShutdownParams &Params) = 0;
+  virtual void onDocumentDidOpen(Ctx C, DidOpenTextDocumentParams &Params) = 0;
+  virtual void onDocumentDidChange(Ctx C,
+                                   DidChangeTextDocumentParams &Params) = 0;
+  virtual void onDocumentDidClose(Ctx C,
+                                  DidCloseTextDocumentParams &Params) = 0;
+  virtual void onDocumentFormatting(Ctx C,
+                                    DocumentFormattingParams &Params) = 0;
+  virtual void
+  onDocumentOnTypeFormatting(Ctx C, DocumentOnTypeFormattingParams &Params) = 0;
+  virtual void
+  onDocumentRangeFormatting(Ctx C, DocumentRangeFormattingParams &Params) = 0;
+  virtual void onCodeAction(Ctx C, CodeActionParams &Params) = 0;
+  virtual void onCompletion(Ctx C, TextDocumentPositionParams &Params) = 0;
+  virtual void onSignatureHelp(Ctx C, TextDocumentPositionParams &Params) = 0;
+  virtual void onGoToDefinition(Ctx C, TextDocumentPositionParams &Params) = 0;
+  virtual void onSwitchSourceHeader(Ctx C, TextDocumentIdentifier &Params) = 0;
+  virtual void onFileEvent(Ctx C, DidChangeWatchedFilesParams &Params) = 0;
 };
 
-void regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, JSONOutput &Out,
-                             ProtocolCallbacks &Callbacks);
+void registerCallbackHandlers(JSONRPCDispatcher &Dispatcher, JSONOutput &Out,
+                              ProtocolCallbacks &Callbacks);
 
 } // namespace clangd
 } // namespace clang
diff --git a/clangd/clients/clangd-vscode/package.json b/clangd/clients/clangd-vscode/package.json
index 6443b11..c048d96 100644
--- a/clangd/clients/clangd-vscode/package.json
+++ b/clangd/clients/clangd-vscode/package.json
@@ -5,7 +5,7 @@
     "version": "0.0.1",
     "publisher": "Unpublished",
     "engines": {
-        "vscode": "^1.8.0"
+        "vscode": "^1.15.0"
     },
     "categories": [
         "Languages",
@@ -24,8 +24,8 @@
         "test": "node ./node_modules/vscode/bin/test"
     },
     "dependencies": {
-        "vscode-languageclient": "^2.6.3",
-        "vscode-languageserver": "^2.6.2"
+        "vscode-languageclient": "^3.3.0",
+        "vscode-languageserver": "^3.3.0"
     },
     "devDependencies": {
         "typescript": "^2.0.3",
@@ -51,6 +51,11 @@
                         "type": "string"
                     },
                     "description": "Arguments for clangd server"
+                },
+                "clangd.syncFileEvents": {
+                    "type": "boolean",
+                    "default": true,
+                    "description": "Whether or not to send file events to clangd (File created, changed or deleted). This can be disabled for performance consideration."
                 }
             }
         }
diff --git a/clangd/clients/clangd-vscode/src/extension.ts b/clangd/clients/clangd-vscode/src/extension.ts
index 7e79f36..f89ddc9 100644
--- a/clangd/clients/clangd-vscode/src/extension.ts
+++ b/clangd/clients/clangd-vscode/src/extension.ts
@@ -18,18 +18,24 @@
 export function activate(context: vscode.ExtensionContext) {
     const clangdPath = getConfig<string>('path');
     const clangdArgs = getConfig<string[]>('arguments');
+    const syncFileEvents = getConfig<boolean>('syncFileEvents', true);
 
     const serverOptions: vscodelc.ServerOptions = { command: clangdPath, args: clangdArgs };
 
+    const cppFileExtensions: string[] = ['cpp', 'c', 'cc', 'cxx', 'c++', 'm', 'mm', 'h', 'hh', 'hpp', 'hxx', 'inc'];
+    const cppFileExtensionsPattern = cppFileExtensions.join();
     const clientOptions: vscodelc.LanguageClientOptions = {
         // Register the server for C/C++ files
-        documentSelector: ['c', 'cc', 'cpp', 'h', 'hh', 'hpp'],
+        documentSelector: cppFileExtensions,
         uriConverters: {
             // FIXME: by default the URI sent over the protocol will be percent encoded (see rfc3986#section-2.1)
             //        the "workaround" below disables temporarily the encoding until decoding
             //        is implemented properly in clangd
             code2Protocol: (uri: vscode.Uri) : string => uri.toString(true),
-            protocol2Code: (uri: string) : vscode.Uri => undefined
+            protocol2Code: (uri: string) : vscode.Uri => vscode.Uri.parse(uri)
+        },
+        synchronize: !syncFileEvents ? undefined : {
+            fileEvents: vscode.workspace.createFileSystemWatcher('**/*.{' + cppFileExtensionsPattern + '}')
         }
     };
 
@@ -42,7 +48,7 @@
         if (textEditor && textEditor.document.uri.toString(true) === uri) {
             textEditor.edit(mutator => {
                 for (const edit of edits) {
-                    mutator.replace(vscodelc.Protocol2Code.asRange(edit.range), edit.newText);
+                    mutator.replace(clangdClient.protocol2CodeConverter.asRange(edit.range), edit.newText);
                 }
             }).then((success) => {
                 if (!success) {
diff --git a/clangd/tool/CMakeLists.txt b/clangd/tool/CMakeLists.txt
index 7e609a3..a40ae04 100644
--- a/clangd/tool/CMakeLists.txt
+++ b/clangd/tool/CMakeLists.txt
@@ -1,11 +1,15 @@
 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
 
-add_clang_executable(clangd
+add_clang_tool(clangd
   ClangdMain.cpp
   )
 
 install(TARGETS clangd RUNTIME DESTINATION bin)
 
+set(LLVM_LINK_COMPONENTS
+  support
+  )
+
 target_link_libraries(clangd
   clangBasic
   clangDaemon
@@ -14,5 +18,4 @@
   clangSema
   clangTooling
   clangToolingCore
-  LLVMSupport
   )
diff --git a/clangd/tool/ClangdMain.cpp b/clangd/tool/ClangdMain.cpp
index d67f75b..cd7d44b 100644
--- a/clangd/tool/ClangdMain.cpp
+++ b/clangd/tool/ClangdMain.cpp
@@ -9,32 +9,110 @@
 
 #include "ClangdLSPServer.h"
 #include "JSONRPCDispatcher.h"
+#include "Path.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
 #include "llvm/Support/Program.h"
-
+#include "llvm/Support/raw_ostream.h"
 #include <iostream>
 #include <memory>
 #include <string>
+#include <thread>
 
 using namespace clang;
 using namespace clang::clangd;
 
-static llvm::cl::opt<bool>
-    RunSynchronously("run-synchronously",
-                     llvm::cl::desc("parse on main thread"),
-                     llvm::cl::init(false), llvm::cl::Hidden);
+static llvm::cl::opt<Path> CompileCommandsDir(
+    "compile-commands-dir",
+    llvm::cl::desc("Specify a path to look for compile_commands.json. If path "
+                   "is invalid, clangd will look in the current directory and "
+                   "parent paths of each source file."));
+
+static llvm::cl::opt<unsigned>
+    WorkerThreadsCount("j",
+                       llvm::cl::desc("Number of async workers used by clangd"),
+                       llvm::cl::init(getDefaultAsyncThreadsCount()));
+
+static llvm::cl::opt<bool> EnableSnippets(
+    "enable-snippets",
+    llvm::cl::desc(
+        "Present snippet completions instead of plaintext completions"),
+    llvm::cl::init(false));
+
+static llvm::cl::opt<bool> RunSynchronously(
+    "run-synchronously",
+    llvm::cl::desc("Parse on main thread. If set, -j is ignored"),
+    llvm::cl::init(false), llvm::cl::Hidden);
+
+static llvm::cl::opt<Path>
+    ResourceDir("resource-dir",
+                llvm::cl::desc("Directory for system clang headers"),
+                llvm::cl::init(""), llvm::cl::Hidden);
+
+static llvm::cl::opt<Path> InputMirrorFile(
+    "input-mirror-file",
+    llvm::cl::desc(
+        "Mirror all LSP input to the specified file. Useful for debugging."),
+    llvm::cl::init(""), llvm::cl::Hidden);
 
 int main(int argc, char *argv[]) {
   llvm::cl::ParseCommandLineOptions(argc, argv, "clangd");
 
+  if (!RunSynchronously && WorkerThreadsCount == 0) {
+    llvm::errs() << "A number of worker threads cannot be 0. Did you mean to "
+                    "specify -run-synchronously?";
+    return 1;
+  }
+
+  // Ignore -j option if -run-synchonously is used.
+  // FIXME: a warning should be shown here.
+  if (RunSynchronously)
+    WorkerThreadsCount = 0;
+
+  /// Validate command line arguments.
+  llvm::Optional<llvm::raw_fd_ostream> InputMirrorStream;
+  if (!InputMirrorFile.empty()) {
+    std::error_code EC;
+    InputMirrorStream.emplace(InputMirrorFile, /*ref*/ EC, llvm::sys::fs::F_RW);
+    if (EC) {
+      InputMirrorStream.reset();
+      llvm::errs() << "Error while opening an input mirror file: "
+                   << EC.message();
+    }
+  }
+
   llvm::raw_ostream &Outs = llvm::outs();
   llvm::raw_ostream &Logs = llvm::errs();
-  JSONOutput Out(Outs, Logs);
+  JSONOutput Out(Outs, Logs,
+                 InputMirrorStream ? InputMirrorStream.getPointer() : nullptr);
 
-  // Change stdin to binary to not lose \r\n on windows.
+  // If --compile-commands-dir arg was invoked, check value and override default
+  // path.
+  namespace path = llvm::sys::path;
+  llvm::Optional<Path> CompileCommandsDirPath;
+
+  if (CompileCommandsDir.empty()) {
+    CompileCommandsDirPath = llvm::None;
+  } else if (!llvm::sys::path::is_absolute(CompileCommandsDir) ||
+             !llvm::sys::fs::exists(CompileCommandsDir)) {
+    llvm::errs() << "Path specified by --compile-commands-dir either does not "
+                    "exist or is not an absolute "
+                    "path. The argument will be ignored.\n";
+    CompileCommandsDirPath = llvm::None;
+  } else {
+    CompileCommandsDirPath = CompileCommandsDir;
+  }
+
+  llvm::Optional<StringRef> ResourceDirRef = None;
+  if (!ResourceDir.empty())
+    ResourceDirRef = ResourceDir;
+
+  /// Change stdin to binary to not lose \r\n on windows.
   llvm::sys::ChangeStdinToBinary();
 
-  ClangdLSPServer LSPServer(Out, RunSynchronously);
+  /// Initialize and run ClangdLSPServer.
+  ClangdLSPServer LSPServer(Out, WorkerThreadsCount, EnableSnippets,
+                            ResourceDirRef, CompileCommandsDirPath);
   LSPServer.run(std::cin);
 }
diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index 85bb8b5..71e00ba 100644
--- a/docs/ReleaseNotes.rst
+++ b/docs/ReleaseNotes.rst
@@ -1,5 +1,5 @@
 ===================================================
-Extra Clang Tools 5.0.0 (In-Progress) Release Notes
+Extra Clang Tools 6.0.0 (In-Progress) Release Notes
 ===================================================
 
 .. contents::
@@ -10,7 +10,7 @@
 
 .. warning::
 
-   These are in-progress notes for the upcoming Extra Clang Tools 5 release.
+   These are in-progress notes for the upcoming Extra Clang Tools 6 release.
    Release notes for previous releases can be found on
    `the Download Page <http://releases.llvm.org/download.html>`_.
 
@@ -18,7 +18,7 @@
 ============
 
 This document contains the release notes for the Extra Clang Tools, part of the
-Clang release 5.0.0. Here we describe the status of the Extra Clang Tools in
+Clang release 6.0.0. Here we describe the status of the Extra Clang Tools in
 some detail, including major improvements from the previous release and new
 feature work. All LLVM releases may be downloaded from the `LLVM releases web
 site <http://llvm.org/releases/>`_.
@@ -32,7 +32,7 @@
 the current one. To see the release notes for a specific release, please
 see the `releases page <http://llvm.org/releases/>`_.
 
-What's New in Extra Clang Tools 5.0.0?
+What's New in Extra Clang Tools 6.0.0?
 ======================================
 
 Some of the major new features and improvements to Extra Clang Tools are listed
@@ -57,82 +57,109 @@
 Improvements to clang-tidy
 --------------------------
 
-- New `cert-dcl21-cpp
-  <http://clang.llvm.org/extra/clang-tidy/checks/cert-dcl21-cpp.html>`_ check
+- Renamed checks to use correct term "implicit conversion" instead of "implicit
+  cast" and modified messages and option names accordingly:
 
-  Checks if the overloaded postfix ``operator++/--`` returns a constant object.
+    * **performance-implicit-cast-in-loop** was renamed to
+      `performance-implicit-conversion-in-loop
+      <http://clang.llvm.org/extra/clang-tidy/checks/performance-implicit-conversion-in-loop.html>`_
+    * **readability-implicit-bool-cast** was renamed to
+      `readability-implicit-bool-conversion
+      <http://clang.llvm.org/extra/clang-tidy/checks/readability-implicit-bool-conversion.html>`_;
+      the check's options were renamed as follows:
+      ``AllowConditionalIntegerCasts`` -> ``AllowIntegerConditions``,
+      ``AllowConditionalPointerCasts`` -> ``AllowPointerConditions``.
 
-- New `cert-dcl58-cpp
-  <http://clang.llvm.org/extra/clang-tidy/checks/cert-dcl58-cpp.html>`_ check
+- New `android-cloexec-accept
+  <http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-accept.html>`_ check
 
-  Finds modification of the ``std`` or ``posix`` namespace.
+  Detects usage of ``accept()``.
 
-- Improved `cppcoreguidelines-no-malloc
-  <http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-no-malloc.html>`_ check
+- New `android-cloexec-accept4
+  <http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-accept4.html>`_ check
 
-  Allow custom memory management functions to be considered as well.
+  Checks if the required file flag ``SOCK_CLOEXEC`` is present in the argument of
+  ``accept4()``.
 
-- New `misc-forwarding-reference-overload
-  <http://clang.llvm.org/extra/clang-tidy/checks/misc-forwarding-reference-overload.html>`_ check
+- New `android-cloexec-dup
+  <http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-dup.html>`_ check
 
-  Finds perfect forwarding constructors that can unintentionally hide copy or move constructors.
+  Detects usage of ``dup()``.
 
-- New `misc-lambda-function-name <http://clang.llvm.org/extra/clang-tidy/checks/misc-lambda-function-name.html>`_ check
+- New `android-cloexec-inotify-init
+  <http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-inotify-init.html>`_ check
 
-  Finds uses of ``__func__`` or ``__FUNCTION__`` inside lambdas.
+  Detects usage of ``inotify_init()``.
 
-- New `modernize-replace-random-shuffle
-  <http://clang.llvm.org/extra/clang-tidy/checks/modernize-replace-random-shuffle.html>`_ check
+- New `android-cloexec-epoll-create1
+  <http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-epoll-create1.html>`_ check
 
-  Finds and fixes usage of ``std::random_shuffle`` as the function has been removed from C++17.
+  Checks if the required file flag ``EPOLL_CLOEXEC`` is present in the argument of
+  ``epoll_create1()``.
 
-- New `modernize-return-braced-init-list
-  <http://clang.llvm.org/extra/clang-tidy/checks/modernize-return-braced-init-list.html>`_ check
+- New `android-cloexec-epoll-create
+  <http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-epoll-create.html>`_ check
 
-  Finds and replaces explicit calls to the constructor in a return statement by
-  a braced initializer list so that the return type is not needlessly repeated.
+  Detects usage of ``epoll_create()``.
 
-- Improved `modernize-use-emplace
-  <http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-emplace.html>`_ check
+- New `android-cloexec-memfd_create
+  <http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-memfd_create.html>`_ check
 
-  Removes unnecessary ``std::make_pair`` and ``std::make_tuple`` calls in
-  push_back calls and turns them into emplace_back. The check now also is able
-  to remove user-defined make functions from ``push_back`` calls on containers
-  of custom tuple-like types by providing `TupleTypes` and `TupleMakeFunctions`.
+  Checks if the required file flag ``MFD_CLOEXEC`` is present in the argument
+  of ``memfd_create()``.
 
-- New `modernize-use-noexcept
-  <http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-noexcept.html>`_ check
+- New `bugprone-integer-division
+  <http://clang.llvm.org/extra/clang-tidy/checks/bugprone-integer-division.html>`_ check
 
-  Replaces dynamic exception specifications with ``noexcept`` or a user defined macro.
+  Finds cases where integer division in a floating point context is likely to
+  cause unintended loss of precision.
 
-- New `performance-inefficient-vector-operation
-  <http://clang.llvm.org/extra/clang-tidy/checks/performance-inefficient-vector-operation.html>`_ check
+- New `cppcoreguidelines-owning-memory <http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-owning-memory.html>`_ check 
 
-  Finds possible inefficient vector operations in for loops that may cause
-  unnecessary memory reallocations.
+  This check implements the type-based semantic of ``gsl::owner<T*>``, but without
+  flow analysis.
 
-- Added `NestingThreshold` to `readability-function-size
-  <http://clang.llvm.org/extra/clang-tidy/checks/readability-function-size.html>`_ check
+- New `hicpp-exception-baseclass
+  <http://clang.llvm.org/extra/clang-tidy/checks/hicpp-exception-baseclass.html>`_ check
 
-  Finds compound statements which create next nesting level after `NestingThreshold` and emits a warning.
+  Ensures that all exception will be instances of ``std::exception`` and classes 
+  that are derived from it.
 
-- Added `ParameterThreshold` to `readability-function-size
-  <http://clang.llvm.org/extra/clang-tidy/checks/readability-function-size.html>`_ check
+- New `hicpp-signed-bitwise
+  <http://clang.llvm.org/extra/clang-tidy/checks/hicpp-signed-bitwise.html>`_ check
 
-  Finds functions that have more than `ParameterThreshold` parameters and emits a warning.
+  Finds uses of bitwise operations on signed integer types, which may lead to 
+  undefined or implementation defined behaviour.
 
-- New `readability-misleading-indentation
-  <http://clang.llvm.org/extra/clang-tidy/checks/readability-misleading-indentation.html>`_ check
+- New `android-cloexec-inotify-init1
+  <http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-inotify-init1.html>`_ check
 
-  Finds misleading indentation where braces should be introduced or the code should be reformatted.
+  Checks if the required file flag ``IN_CLOEXEC`` is present in the argument of
+  ``inotify_init1()``.
 
-- Support clang-formatting of the code around applied fixes (``-format-style``
-  command-line option).
+- New `readability-static-accessed-through-instance
+  <http://clang.llvm.org/extra/clang-tidy/checks/readability-static-accessed-through-instance.html>`_ check
 
-- New `hicpp` module
+  Finds member expressions that access static members through instances and
+  replaces them with uses of the appropriate qualified-id.
 
-  Adds checks that implement the `High Integrity C++ Coding Standard <http://www.codingstandard.com/section/index/>`_ and other safety
-  standards. Many checks are aliased to other modules.
+- Added `modernize-use-emplace.IgnoreImplicitConstructors
+  <http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-emplace.html#cmdoption-arg-IgnoreImplicitConstructors>`_
+  option.
+
+- Added aliases for the `High Integrity C++ Coding Standard <http://www.codingstandard.com/section/index/>`_ 
+  to already implemented checks in other modules.
+
+  - `hicpp-deprecated-headers <http://clang.llvm.org/extra/clang-tidy/checks/hicpp-deprecated-headers.html>`_
+  - `hicpp-move-const-arg <http://clang.llvm.org/extra/clang-tidy/checks/hicpp-move-const-arg.html>`_
+  - `hicpp-no-array-decay <http://clang.llvm.org/extra/clang-tidy/checks/hicpp-no-array-decay.html>`_
+  - `hicpp-no-malloc <http://clang.llvm.org/extra/clang-tidy/checks/hicpp-no-malloc.html>`_
+  - `hicpp-static-assert <http://clang.llvm.org/extra/clang-tidy/checks/hicpp-static-assert.html>`_
+  - `hicpp-use-auto <http://clang.llvm.org/extra/clang-tidy/checks/hicpp-use-auto.html>`_
+  - `hicpp-use-emplace <http://clang.llvm.org/extra/clang-tidy/checks/hicpp-use-emplace.html>`_
+  - `hicpp-use-noexcept <http://clang.llvm.org/extra/clang-tidy/checks/hicpp-use-noexcept.html>`_
+  - `hicpp-use-nullptr <http://clang.llvm.org/extra/clang-tidy/checks/hicpp-use-nullptr.html>`_
+  - `hicpp-vararg <http://clang.llvm.org/extra/clang-tidy/checks/hicpp-vararg.html>`_
 
 Improvements to include-fixer
 -----------------------------
diff --git a/docs/clang-tidy/checks/android-cloexec-accept.rst b/docs/clang-tidy/checks/android-cloexec-accept.rst
new file mode 100644
index 0000000..58ce05f
--- /dev/null
+++ b/docs/clang-tidy/checks/android-cloexec-accept.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - android-cloexec-accept
+
+android-cloexec-accept
+======================
+
+The usage of ``accept()`` is not recommended, it's better to use ``accept4()``.
+Without this flag, an opened sensitive file descriptor would remain open across
+a fork+exec to a lower-privileged SELinux domain.
+
+Examples:
+
+.. code-block:: c++
+
+  accept(sockfd, addr, addrlen);
+
+  // becomes
+
+  accept4(sockfd, addr, addrlen, SOCK_CLOEXEC);
diff --git a/docs/clang-tidy/checks/android-cloexec-accept4.rst b/docs/clang-tidy/checks/android-cloexec-accept4.rst
new file mode 100644
index 0000000..1633395
--- /dev/null
+++ b/docs/clang-tidy/checks/android-cloexec-accept4.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - android-cloexec-accept4
+
+android-cloexec-accept4
+=======================
+
+``accept4()`` should include ``SOCK_CLOEXEC`` in its type argument to avoid the
+file descriptor leakage. Without this flag, an opened sensitive file would
+remain open across a fork+exec to a lower-privileged SELinux domain.
+
+Examples:
+
+.. code-block:: c++
+
+  accept4(sockfd, addr, addrlen, SOCK_NONBLOCK);
+
+  // becomes
+
+  accept4(sockfd, addr, addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC);
diff --git a/docs/clang-tidy/checks/android-cloexec-creat.rst b/docs/clang-tidy/checks/android-cloexec-creat.rst
new file mode 100644
index 0000000..d2892a0
--- /dev/null
+++ b/docs/clang-tidy/checks/android-cloexec-creat.rst
@@ -0,0 +1,16 @@
+.. title:: clang-tidy - android-cloexec-creat
+
+android-cloexec-creat
+=====================
+
+The usage of ``creat()`` is not recommended, it's better to use ``open()``.
+
+Examples:
+
+.. code-block:: c++
+
+  int fd = creat(path, mode);
+
+  // becomes
+
+  int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode);
diff --git a/docs/clang-tidy/checks/android-cloexec-dup.rst b/docs/clang-tidy/checks/android-cloexec-dup.rst
new file mode 100644
index 0000000..d287a65
--- /dev/null
+++ b/docs/clang-tidy/checks/android-cloexec-dup.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - android-cloexec-dup
+
+android-cloexec-dup
+===================
+
+The usage of ``dup()`` is not recommended, it's better to use ``fcntl()``,
+which can set the close-on-exec flag. Otherwise, an opened sensitive file would
+remain open across a fork+exec to a lower-privileged SELinux domain.
+
+Examples:
+
+.. code-block:: c++
+
+  int fd = dup(oldfd);
+
+  // becomes
+
+  int fd = fcntl(oldfd, F_DUPFD_CLOEXEC);
diff --git a/docs/clang-tidy/checks/android-cloexec-epoll-create.rst b/docs/clang-tidy/checks/android-cloexec-epoll-create.rst
new file mode 100644
index 0000000..98f0f6c
--- /dev/null
+++ b/docs/clang-tidy/checks/android-cloexec-epoll-create.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - android-cloexec-epoll-create
+
+android-cloexec-epoll-create
+============================
+
+The usage of ``epoll_create()`` is not recommended, it's better to use
+``epoll_create1()``, which allows close-on-exec.
+
+Examples:
+
+.. code-block:: c++
+
+  epoll_create(size);
+
+  // becomes
+
+  epoll_create1(EPOLL_CLOEXEC);
diff --git a/docs/clang-tidy/checks/android-cloexec-epoll-create1.rst b/docs/clang-tidy/checks/android-cloexec-epoll-create1.rst
new file mode 100644
index 0000000..7e7c4ad
--- /dev/null
+++ b/docs/clang-tidy/checks/android-cloexec-epoll-create1.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - android-cloexec-epoll-create1
+
+android-cloexec-epoll-create1
+=============================
+
+``epoll_create1()`` should include ``EPOLL_CLOEXEC`` in its type argument to
+avoid the file descriptor leakage. Without this flag, an opened sensitive file
+would remain open across a fork+exec to a lower-privileged SELinux domain.
+
+Examples:
+
+.. code-block:: c++
+
+  epoll_create1(0);
+
+  // becomes
+
+  epoll_create1(EPOLL_CLOEXEC);
diff --git a/docs/clang-tidy/checks/android-cloexec-fopen.rst b/docs/clang-tidy/checks/android-cloexec-fopen.rst
new file mode 100644
index 0000000..0552969
--- /dev/null
+++ b/docs/clang-tidy/checks/android-cloexec-fopen.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - android-cloexec-fopen
+
+android-cloexec-fopen
+=====================
+
+``fopen()`` should include ``e`` in their mode string; so ``re`` would be
+valid. This is equivalent to having set ``FD_CLOEXEC on`` that descriptor.
+
+Examples:
+
+.. code-block:: c++
+
+  fopen("fn", "r");
+
+  // becomes
+
+  fopen("fn", "re");
+
diff --git a/docs/clang-tidy/checks/android-cloexec-inotify-init.rst b/docs/clang-tidy/checks/android-cloexec-inotify-init.rst
new file mode 100644
index 0000000..cee4c7b
--- /dev/null
+++ b/docs/clang-tidy/checks/android-cloexec-inotify-init.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - android-cloexec-inotify-init
+
+android-cloexec-inotify-init
+============================
+
+The usage of ``inotify_init()`` is not recommended, it's better to use
+``inotify_init1()``.
+
+Examples:
+
+.. code-block:: c++
+
+  inotify_init();
+
+  // becomes
+
+  inotify_init1(IN_CLOEXEC);
diff --git a/docs/clang-tidy/checks/android-cloexec-inotify-init1.rst b/docs/clang-tidy/checks/android-cloexec-inotify-init1.rst
new file mode 100644
index 0000000..827598c
--- /dev/null
+++ b/docs/clang-tidy/checks/android-cloexec-inotify-init1.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - android-cloexec-inotify-init1
+
+android-cloexec-inotify-init1
+=============================
+
+``inotify_init1()`` should include ``IN_CLOEXEC`` in its type argument to avoid the
+file descriptor leakage. Without this flag, an opened sensitive file would
+remain open across a fork+exec to a lower-privileged SELinux domain.
+
+Examples:
+
+.. code-block:: c++
+
+  inotify_init1(IN_NONBLOCK);
+
+  // becomes
+
+  inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
diff --git a/docs/clang-tidy/checks/android-cloexec-memfd-create.rst b/docs/clang-tidy/checks/android-cloexec-memfd-create.rst
new file mode 100644
index 0000000..a45321d
--- /dev/null
+++ b/docs/clang-tidy/checks/android-cloexec-memfd-create.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - android-cloexec-memfd-create
+
+android-cloexec-memfd-create
+============================
+
+``memfd_create()`` should include ``MFD_CLOEXEC`` in its type argument to avoid
+the file descriptor leakage. Without this flag, an opened sensitive file would
+remain open across a fork+exec to a lower-privileged SELinux domain.
+
+Examples:
+
+.. code-block:: c++
+
+  memfd_create(name, MFD_ALLOW_SEALING);
+
+  // becomes
+
+  memfd_create(name, MFD_ALLOW_SEALING | MFD_CLOEXEC);
diff --git a/docs/clang-tidy/checks/android-cloexec-open.rst b/docs/clang-tidy/checks/android-cloexec-open.rst
new file mode 100644
index 0000000..ee3e4b5
--- /dev/null
+++ b/docs/clang-tidy/checks/android-cloexec-open.rst
@@ -0,0 +1,24 @@
+.. title:: clang-tidy - android-cloexec-open
+
+android-cloexec-open
+====================
+
+A common source of security bugs is code that opens a file without using the
+``O_CLOEXEC`` flag.  Without that flag, an opened sensitive file would remain
+open across a fork+exec to a lower-privileged SELinux domain, leaking that
+sensitive data. Open-like functions including ``open()``, ``openat()``, and
+``open64()`` should include ``O_CLOEXEC`` in their flags argument.
+
+Examples:
+
+.. code-block:: c++
+
+  open("filename", O_RDWR);
+  open64("filename", O_RDWR);
+  openat(0, "filename", O_RDWR);
+
+  // becomes
+
+  open("filename", O_RDWR | O_CLOEXEC);
+  open64("filename", O_RDWR | O_CLOEXEC);
+  openat(0, "filename", O_RDWR | O_CLOEXEC);
diff --git a/docs/clang-tidy/checks/android-cloexec-socket.rst b/docs/clang-tidy/checks/android-cloexec-socket.rst
new file mode 100644
index 0000000..10b1976
--- /dev/null
+++ b/docs/clang-tidy/checks/android-cloexec-socket.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - android-cloexec-socket
+
+android-cloexec-socket
+======================
+
+``socket()`` should include ``SOCK_CLOEXEC`` in its type argument to avoid the
+file descriptor leakage. Without this flag, an opened sensitive file would
+remain open across a fork+exec to a lower-privileged SELinux domain.
+
+Examples:
+
+.. code-block:: c++
+
+  socket(domain, type, SOCK_STREAM);
+
+  // becomes
+
+  socket(domain, type, SOCK_STREAM | SOCK_CLOEXEC);
diff --git a/docs/clang-tidy/checks/bugprone-integer-division.rst b/docs/clang-tidy/checks/bugprone-integer-division.rst
new file mode 100644
index 0000000..2c82e6f
--- /dev/null
+++ b/docs/clang-tidy/checks/bugprone-integer-division.rst
@@ -0,0 +1,39 @@
+.. title:: clang-tidy - bugprone-integer-division
+
+bugprone-integer-division
+=========================
+
+Finds cases where integer division in a floating point context is likely to
+cause unintended loss of precision.
+
+No reports are made if divisions are part of the following expressions:
+
+- operands of operators expecting integral or bool types,
+- call expressions of integral or bool types, and
+- explicit cast expressions to integral or bool types,
+
+as these are interpreted as signs of deliberateness from the programmer.
+
+Examples:
+
+.. code-block:: c++
+
+  float floatFunc(float);
+  int intFunc(int);
+  double d;
+  int i = 42;
+
+  // Warn, floating-point values expected.
+  d = 32 * 8 / (2 + i);
+  d = 8 * floatFunc(1 + 7 / 2);
+  d = i / (1 << 4);
+
+  // OK, no integer division.
+  d = 32 * 8.0 / (2 + i);
+  d = 8 * floatFunc(1 + 7.0 / 2);
+  d = (double)i / (1 << 4);
+
+  // OK, there are signs of deliberateness.
+  d = 1 << (i / 2);
+  d = 9 + intFunc(6 * i / 32);
+  d = (int)(i / 32) - 8;
diff --git a/docs/clang-tidy/checks/bugprone-suspicious-memset-usage.rst b/docs/clang-tidy/checks/bugprone-suspicious-memset-usage.rst
new file mode 100644
index 0000000..82609d1
--- /dev/null
+++ b/docs/clang-tidy/checks/bugprone-suspicious-memset-usage.rst
@@ -0,0 +1,54 @@
+.. title:: clang-tidy - bugprone-suspicious-memset-usage
+
+bugprone-suspicious-memset-usage
+================================
+
+This check finds ``memset()`` calls with potential mistakes in their arguments.
+Considering the function as ``void* memset(void* destination, int fill_value,
+size_t byte_count)``, the following cases are covered:
+
+**Case 1: Fill value is a character ``'0'``**
+
+Filling up a memory area with ASCII code 48 characters is not customary,
+possibly integer zeroes were intended instead.
+The check offers a replacement of ``'0'`` with ``0``. Memsetting character
+pointers with ``'0'`` is allowed.
+
+**Case 2: Fill value is truncated**
+
+Memset converts ``fill_value`` to ``unsigned char`` before using it. If
+``fill_value`` is out of unsigned character range, it gets truncated
+and memory will not contain the desired pattern.
+
+**Case 3: Byte count is zero**
+
+Calling memset with a literal zero in its ``byte_count`` argument is likely
+to be unintended and swapped with ``fill_value``. The check offers to swap
+these two arguments.
+
+Corresponding cpplint.py check name: ``runtime/memset``.
+
+
+Examples:
+
+.. code-block:: c++
+
+  void foo() {
+    int i[5] = {1, 2, 3, 4, 5};
+    int *ip = i;
+    char c = '1';
+    char *cp = &c;
+    int v = 0;
+
+    // Case 1
+    memset(ip, '0', 1); // suspicious
+    memset(cp, '0', 1); // OK
+
+    // Case 2
+    memset(ip, 0xabcd, 1); // fill value gets truncated
+    memset(ip, 0x00, 1);   // OK
+
+    // Case 3
+    memset(ip, sizeof(int), v); // zero length, potentially swapped
+    memset(ip, 0, 1);           // OK
+  }
diff --git a/docs/clang-tidy/checks/bugprone-undefined-memory-manipulation.rst b/docs/clang-tidy/checks/bugprone-undefined-memory-manipulation.rst
new file mode 100644
index 0000000..2735184
--- /dev/null
+++ b/docs/clang-tidy/checks/bugprone-undefined-memory-manipulation.rst
@@ -0,0 +1,7 @@
+.. title:: clang-tidy - bugprone-undefined-memory-manipulation
+
+bugprone-undefined-memory-manipulation
+======================================
+
+Finds calls of memory manipulation functions ``memset()``, ``memcpy()`` and
+``memmove()`` on not TriviallyCopyable objects resulting in undefined behavior.
diff --git a/docs/clang-tidy/checks/cppcoreguidelines-c-copy-assignment-signature.rst b/docs/clang-tidy/checks/cppcoreguidelines-c-copy-assignment-signature.rst
new file mode 100644
index 0000000..9096ef4
--- /dev/null
+++ b/docs/clang-tidy/checks/cppcoreguidelines-c-copy-assignment-signature.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - cppcoreguidelines-c-copy-assignment-signature
+.. meta::
+   :http-equiv=refresh: 5;URL=misc-unconventional-assign-operator.html
+
+cppcoreguidelines-c-copy-assignment-signature
+=============================================
+
+The cppcoreguidelines-c-copy-assignment-signature check is an alias, please see
+`misc-unconventional-assign-operator <misc-unconventional-assign-operator.html>`_
+for more information.
diff --git a/docs/clang-tidy/checks/cppcoreguidelines-owning-memory.rst b/docs/clang-tidy/checks/cppcoreguidelines-owning-memory.rst
new file mode 100644
index 0000000..116b335
--- /dev/null
+++ b/docs/clang-tidy/checks/cppcoreguidelines-owning-memory.rst
@@ -0,0 +1,172 @@
+.. title:: clang-tidy - cppcoreguidelines-owning-memory
+
+cppcoreguidelines-owning-memory
+===============================
+
+This check implements the type-based semantics of ``gsl::owner<T*>``, which allows 
+static analysis on code, that uses raw pointers to handle resources like 
+dynamic memory, but won't introduce RAII concepts.
+
+The relevant sections in the `C++ Core Guidelines <https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md>`_ are I.11, C.33, R.3 and GSL.Views
+The definition of a ``gsl::owner<T*>`` is straight forward
+
+.. code-block:: c++
+
+  namespace gsl { template <typename T> owner = T; }
+
+It is therefore simple to introduce the owner even without using an implementation of
+the `Guideline Support Library <https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#gsl-guideline-support-library>`_.
+
+All checks are purely type based and not (yet) flow sensitive.
+
+The following examples will demonstrate the correct and incorrect initializations
+of owners, assignment is handled the same way. Note that both ``new`` and 
+``malloc()``-like resource functions are considered to produce resources.
+
+.. code-block:: c++
+
+  // Creating an owner with factory functions is checked.
+  gsl::owner<int*> function_that_returns_owner() { return gsl::owner<int*>(new int(42)); }
+
+  // Dynamic memory must be assigned to an owner
+  int* Something = new int(42); // BAD, will be caught
+  gsl::owner<int*> Owner = new int(42); // Good
+  gsl::owner<int*> Owner = new int[42]; // Good as well
+
+  // Returned owner must be assigned to an owner
+  int* Something = function_that_returns_owner(); // Bad, factory function
+  gsl::owner<int*> Owner = function_that_returns_owner(); // Good, result lands in owner
+
+  // Something not a resource or owner should not be assigned to owners
+  int Stack = 42;
+  gsl::owner<int*> Owned = &Stack; // Bad, not a resource assigned
+
+In the case of dynamic memory as resource, only ``gsl::owner<T*>`` variables are allowed
+to be deleted.
+
+.. code-block:: c++
+
+  // Example Bad, non-owner as resource handle, will be caught.
+  int* NonOwner = new int(42); // First warning here, since new must land in an owner
+  delete NonOwner; // Second warning here, since only owners are allowed to be deleted
+
+  // Example Good, Ownership correclty stated
+  gsl::owner<int*> Owner = new int(42); // Good
+  delete Owner; // Good as well, statically enforced, that only owners get deleted
+  
+The check will furthermore ensure, that functions, that expect a ``gsl::owner<T*>`` as
+argument get called with either a ``gsl::owner<T*>`` or a newly created resource.
+
+.. code-block:: c++
+
+  void expects_owner(gsl::owner<int*> o) { delete o; }
+
+  // Bad Code
+  int NonOwner = 42;
+  expects_owner(&NonOwner); // Bad, will get caught
+
+  // Good Code
+  gsl::owner<int*> Owner = new int(42);
+  expects_owner(Owner); // Good
+  expects_owner(new int(42)); // Good as well, recognized created resource
+
+  // Port legacy code for better resource-safety
+  gsl::owner<FILE*> File = fopen("my_file.txt", "rw+");
+  FILE* BadFile = fopen("another_file.txt", "w"); // Bad, warned
+
+  // ... use the file
+
+  fclose(File); // Ok, File is annotated as 'owner<>'
+  fclose(BadFile); // BadFile is not an 'owner<>', will be warned
+
+
+Options
+-------
+
+.. option:: LegacyResourceProducers
+
+   Semicolon-separated list of fully qualified names of legacy functions that create
+   resources but cannot introduce ``gsl::owner<>``.
+   Defaults to ``::malloc;::aligned_alloc;::realloc;::calloc;::fopen;::freopen;::tmpfile``.
+
+
+.. option:: LegacyResourceConsumers
+
+   Semicolon-separated list of fully qualified names of legacy functions expecting
+   resource owners as pointer arguments but cannot introduce ``gsl::owner<>``.
+   Defaults to ``::free;::realloc;::freopen;::fclose``.
+
+
+Limitations
+-----------
+
+Using ``gsl::owner<T*>`` in a typedef or alias is not handled correctly. 
+
+.. code-block:: c++
+
+  using heap_int = gsl::owner<int*>;
+  heap_int allocated = new int(42); // False positive!
+
+The ``gsl::owner<T*>`` is declared as a templated type alias.
+In template functions and classes, like in the example below, the information
+of the type aliases gets lost. Therefore using ``gsl::owner<T*>`` in a heavy templated
+code base might lead to false positives. 
+This limitation results in ``std::vector<gsl::owner<T*>>`` not being diagnosed correctly.
+
+.. code-block:: c++
+
+  // This template function works as expected. Type information doesn't get lost.
+  template <typename T>
+  void delete_owner(gsl::owner<T*> owned_object) {
+    delete owned_object; // Everything alright
+  }
+
+  gsl::owner<int*> function_that_returns_owner() { return gsl::owner<int*>(new int(42)); }
+
+  // Type deduction does not work for auto variables. 
+  // This is caught by the check and will be noted accordingly.
+  auto OwnedObject = function_that_returns_owner(); // Type of OwnedObject will be int*
+
+  // Problematic function template that looses the typeinformation on owner
+  template <typename T>
+  void bad_template_function(T some_object) {
+    // This line will trigger the warning, that a non-owner is assigned to an owner
+    gsl::owner<T*> new_owner = some_object;
+  }
+
+  // Calling the function with an owner still yields a false positive.
+  bad_template_function(gsl::owner<int*>(new int(42)));
+
+
+  // The same issue occurs with templated classes like the following.
+  template <typename T>
+  class OwnedValue {
+  public:
+    const T getValue() const { return _val; }
+  private:
+    T _val;
+  };
+
+  // Code, that yields a false positive.
+  OwnedValue<gsl::owner<int*>> Owner(new int(42)); // Type deduction yield T -> int * 
+  // False positive, getValue returns int* and not gsl::owner<int*>
+  gsl::owner<int*> OwnedInt = Owner.getValue(); 
+
+Another limitation of the current implementation is only the type based checking.
+Suppose you have code like the following:
+
+.. code-block:: c++
+
+  // Two owners with assigned resources
+  gsl::owner<int*> Owner1 = new int(42); 
+  gsl::owner<int*> Owner2 = new int(42);
+
+  Owner2 = Owner1; // Conceptual Leak of initial resource of Owner2!
+  Owner1 = nullptr;
+
+The semantic of a ``gsl::owner<T*>`` is mostly like a ``std::unique_ptr<T>``, therefore
+assignment of two ``gsl::owner<T*>`` is considered a move, which requires that the 
+resource ``Owner2`` must have been released before the assignment.
+This kind of condition could be catched in later improvements of this check with 
+flowsensitive analysis. Currently, the `Clang Static Analyzer` catches this bug
+for dynamic memory, but not for general types of resources.
diff --git a/docs/clang-tidy/checks/google-runtime-memset.rst b/docs/clang-tidy/checks/google-runtime-memset.rst
deleted file mode 100644
index 3832b6e..0000000
--- a/docs/clang-tidy/checks/google-runtime-memset.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-.. title:: clang-tidy - google-runtime-memset
-
-google-runtime-memset
-=====================
-
-Finds calls to ``memset`` with a literal zero in the length argument.
-
-This is most likely unintended and the length and value arguments are swapped.
-
-Corresponding cpplint.py check name: `runtime/memset`.
diff --git a/docs/clang-tidy/checks/hicpp-braces-around-statements.rst b/docs/clang-tidy/checks/hicpp-braces-around-statements.rst
new file mode 100644
index 0000000..2931aa8
--- /dev/null
+++ b/docs/clang-tidy/checks/hicpp-braces-around-statements.rst
@@ -0,0 +1,11 @@
+.. title:: clang-tidy - hicpp-braces-around-statements
+.. meta::
+   :http-equiv=refresh: 5;URL=readability-braces-around-statements.html
+
+hicpp-braces-around-statements
+==============================
+
+The `hicpp-braces-around-statements` check is an alias, please see
+`readability-braces-around-statements <readability-braces-around-statements.html>`_
+for more information.
+It enforces the `rule 6.1.1 <http://www.codingstandard.com/rule/6-1-1-enclose-the-body-of-a-selection-or-an-iteration-statement-in-a-compound-statement/>`_.
diff --git a/docs/clang-tidy/checks/hicpp-deprecated-headers.rst b/docs/clang-tidy/checks/hicpp-deprecated-headers.rst
new file mode 100644
index 0000000..960d918
--- /dev/null
+++ b/docs/clang-tidy/checks/hicpp-deprecated-headers.rst
@@ -0,0 +1,11 @@
+.. title:: clang-tidy - hicpp-deprecated-headers
+.. meta::
+   :http-equiv=refresh: 5;URL=modernize-deprecated-headers.html
+
+hicpp-deprecated-headers
+========================
+
+The `hicpp-deprecated-headers` check is an alias, please see
+`modernize-deprecated-headers <modernize-deprecated-headers.html>`_
+for more information.
+It enforces the `rule 1.3.3 <http://www.codingstandard.com/rule/1-3-3-do-not-use-the-c-standard-library-h-headers/>`_.
diff --git a/docs/clang-tidy/checks/hicpp-exception-baseclass.rst b/docs/clang-tidy/checks/hicpp-exception-baseclass.rst
new file mode 100644
index 0000000..42563ae
--- /dev/null
+++ b/docs/clang-tidy/checks/hicpp-exception-baseclass.rst
@@ -0,0 +1,30 @@
+.. title:: clang-tidy - hicpp-exception-baseclass
+
+hicpp-exception-baseclass
+=========================
+
+Ensure that every value that in a ``throw`` expression is an instance of 
+``std::exception``.
+
+This enforces `rule 15.1 <http://www.codingstandard.com/section/15-1-throwing-an-exception/>`_
+of the High Integrity C++ Coding Standard.
+
+.. code-block:: c++
+
+  class custom_exception {};
+
+  void throwing() noexcept(false) {
+    // Problematic throw expressions.
+    throw int(42);
+    throw custom_exception();
+  }
+
+  class mathematical_error : public std::exception {};
+
+  void throwing2() noexcept(false) {
+    // These kind of throws are ok.
+    throw mathematical_error();
+    throw std::runtime_error();
+    throw std::exception();
+  }
+  
diff --git a/docs/clang-tidy/checks/hicpp-explicit-conversions.rst b/docs/clang-tidy/checks/hicpp-explicit-conversions.rst
index 1779473..3ee0b78 100644
--- a/docs/clang-tidy/checks/hicpp-explicit-conversions.rst
+++ b/docs/clang-tidy/checks/hicpp-explicit-conversions.rst
@@ -1,9 +1,11 @@
 .. title:: clang-tidy - hicpp-explicit-conversions
+.. meta::
+   :http-equiv=refresh: 5;URL=google-explicit-constructor.html
 
 hicpp-explicit-conversions
 ==========================
 
-This check is an alias for `google-explicit-constructor <google-explicit-constructor.hml>`_.
+This check is an alias for `google-explicit-constructor <google-explicit-constructor.html>`_.
 Used to enforce parts of `rule 5.4.1 <http://www.codingstandard.com/rule/5-4-1-only-use-casting-forms-static_cast-excl-void-dynamic_cast-or-explicit-constructor-call/>`_.
 This check will enforce that constructors and conversion operators are marked `explicit`.
 Other forms of casting checks are implemented in other places.
diff --git a/docs/clang-tidy/checks/hicpp-function-size.rst b/docs/clang-tidy/checks/hicpp-function-size.rst
index b82a722..4b1f616 100644
--- a/docs/clang-tidy/checks/hicpp-function-size.rst
+++ b/docs/clang-tidy/checks/hicpp-function-size.rst
@@ -1,9 +1,11 @@
 .. title:: clang-tidy - hicpp-function-size
+.. meta::
+   :http-equiv=refresh: 5;URL=readability-function-size.html
 
 hicpp-function-size
 ===================
 
-This check is an alias for `readability-function-size <readability-function-size.hml>`_.
+This check is an alias for `readability-function-size <readability-function-size.html>`_.
 Useful to enforce multiple sections on function complexity.
 
 - `rule 8.2.2 <http://www.codingstandard.com/rule/8-2-2-do-not-declare-functions-with-an-excessive-number-of-parameters/>`_
diff --git a/docs/clang-tidy/checks/hicpp-invalid-access-moved.rst b/docs/clang-tidy/checks/hicpp-invalid-access-moved.rst
index d016eae..fa0ed37 100644
--- a/docs/clang-tidy/checks/hicpp-invalid-access-moved.rst
+++ b/docs/clang-tidy/checks/hicpp-invalid-access-moved.rst
@@ -1,8 +1,10 @@
 .. title:: clang-tidy - hicpp-invalid-access-moved
+.. meta::
+   :http-equiv=refresh: 5;URL=misc-use-after-move.html
 
 hicpp-invalid-access-moved
 ==========================
 
-This check is an alias for `misc-use-after-move <misc-use-after-move.hml>`_.
+This check is an alias for `misc-use-after-move <misc-use-after-move.html>`_.
 
 Implements parts of the `rule 8.4.1 <http://www.codingstandard.com/rule/8-4-1-do-not-access-an-invalid-object-or-an-object-with-indeterminate-value/>`_ to check if moved-from objects are accessed.
diff --git a/docs/clang-tidy/checks/hicpp-member-init.rst b/docs/clang-tidy/checks/hicpp-member-init.rst
index eb948ae..7f985e2 100644
--- a/docs/clang-tidy/checks/hicpp-member-init.rst
+++ b/docs/clang-tidy/checks/hicpp-member-init.rst
@@ -1,9 +1,11 @@
 .. title:: clang-tidy - hicpp-member-init
+.. meta::
+   :http-equiv=refresh: 5;URL=cppcoreguidelines-pro-type-member-init.html
 
 hicpp-member-init
 =================
 
-This check is an alias for `cppcoreguidelines-pro-type-member-init <cppcoreguidelines-pro-type-member-init.hml>`_.
+This check is an alias for `cppcoreguidelines-pro-type-member-init <cppcoreguidelines-pro-type-member-init.html>`_.
 Implements the check for 
 `rule 12.4.2 <http://www.codingstandard.com/rule/12-4-2-ensure-that-a-constructor-initializes-explicitly-all-base-classes-and-non-static-data-members/>`_ 
 to initialize class members in the right order.
diff --git a/docs/clang-tidy/checks/hicpp-move-const-arg.rst b/docs/clang-tidy/checks/hicpp-move-const-arg.rst
new file mode 100644
index 0000000..790ac78
--- /dev/null
+++ b/docs/clang-tidy/checks/hicpp-move-const-arg.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - hicpp-move-const-arg
+.. meta::
+   :http-equiv=refresh: 5;URL=misc-move-const-arg.html
+
+hicpp-move-const-arg
+====================
+
+The `hicpp-move-const-arg` check is an alias, please see
+`misc-move-const-arg <misc-move-const-arg.html>`_ for more information.
+It enforces the `rule 17.3.1 <http://www.codingstandard.com/rule/17-3-1-do-not-use-stdmove-on-objects-declared-with-const-or-const-type/>`_.
diff --git a/docs/clang-tidy/checks/hicpp-named-parameter.rst b/docs/clang-tidy/checks/hicpp-named-parameter.rst
index d848d07..4bb8505 100644
--- a/docs/clang-tidy/checks/hicpp-named-parameter.rst
+++ b/docs/clang-tidy/checks/hicpp-named-parameter.rst
@@ -1,8 +1,10 @@
 .. title:: clang-tidy - hicpp-named-parameter
+.. meta::
+   :http-equiv=refresh: 5;URL=readability-named-parameter.html
 
 hicpp-named-parameter
 =====================
 
-This check is an alias for `readability-named-parameter <readability-named-parameter.hml>`_.
+This check is an alias for `readability-named-parameter <readability-named-parameter.html>`_.
 
 Implements `rule 8.2.1 <http://www.codingstandard.com/rule/8-2-1-make-parameter-names-absent-or-identical-in-all-declarations/>`_.
diff --git a/docs/clang-tidy/checks/hicpp-new-delete-operators.rst b/docs/clang-tidy/checks/hicpp-new-delete-operators.rst
index 8994644..88c26ad 100644
--- a/docs/clang-tidy/checks/hicpp-new-delete-operators.rst
+++ b/docs/clang-tidy/checks/hicpp-new-delete-operators.rst
@@ -1,8 +1,10 @@
 .. title:: clang-tidy - hicpp-new-delete-operators
+.. meta::
+   :http-equiv=refresh: 5;URL=misc-new-delete-overloads.html
 
 hicpp-new-delete-operators
 ==========================
 
-This check is an alias for `misc-new-delete-overloads <misc-new-delete-overloads.hml>`_.
+This check is an alias for `misc-new-delete-overloads <misc-new-delete-overloads.html>`_.
 Implements `rule 12.3.1 <http://www.codingstandard.com/section/12-3-free-store/>`_ to ensure
 the `new` and `delete` operators have the correct signature.
diff --git a/docs/clang-tidy/checks/hicpp-no-array-decay.rst b/docs/clang-tidy/checks/hicpp-no-array-decay.rst
new file mode 100644
index 0000000..01f140e
--- /dev/null
+++ b/docs/clang-tidy/checks/hicpp-no-array-decay.rst
@@ -0,0 +1,11 @@
+.. title:: clang-tidy - hicpp-no-array-decay
+.. meta::
+   :http-equiv=refresh: 5;URL=cppcoreguidelines-pro-bounds-array-to-pointer-decay.html
+
+hicpp-no-array-decay
+====================
+
+The `hicpp-no-array-decay` check is an alias, please see
+`cppcoreguidelines-pro-bounds-array-to-pointer-decay <cppcoreguidelines-pro-bounds-array-to-pointer-decay.html>`_
+for more information.
+It enforces the `rule 4.1.1 <http://www.codingstandard.com/section/4-1-array-to-pointer-conversion/>`_.
diff --git a/docs/clang-tidy/checks/hicpp-no-malloc.rst b/docs/clang-tidy/checks/hicpp-no-malloc.rst
new file mode 100644
index 0000000..768342f
--- /dev/null
+++ b/docs/clang-tidy/checks/hicpp-no-malloc.rst
@@ -0,0 +1,11 @@
+.. title:: clang-tidy - hicpp-no-malloc
+.. meta::
+   :http-equiv=refresh: 5;URL=cppcoreguidelines-no-malloc.html
+
+hicpp-no-malloc
+===============
+
+The `hicpp-no-malloc` check is an alias, please see
+`cppcoreguidelines-no-malloc <cppcoreguidelines-no-malloc.html>`_
+for more information.
+It enforces the `rule 5.3.2 <http://www.codingstandard.com/rule/5-3-2-allocate-memory-using-new-and-release-it-using-delete/>`_.
diff --git a/docs/clang-tidy/checks/hicpp-noexcept-move.rst b/docs/clang-tidy/checks/hicpp-noexcept-move.rst
index 0f4505f..10573ec 100644
--- a/docs/clang-tidy/checks/hicpp-noexcept-move.rst
+++ b/docs/clang-tidy/checks/hicpp-noexcept-move.rst
@@ -1,7 +1,9 @@
 .. title:: clang-tidy - hicpp-noexcept-move
+.. meta::
+   :http-equiv=refresh: 5;URL=misc-noexcept-moveconstructor.html
 
 hicpp-noexcept-move
 ===================
 
-This check is an alias for `misc-noexcept-moveconstructor <misc-noexcept-moveconstructor.hml>`_.
+This check is an alias for `misc-noexcept-moveconstructor <misc-noexcept-moveconstructor.html>`_.
 Checks `rule 12.5.4 <http://www.codingstandard.com/rule/12-5-4-declare-noexcept-the-move-constructor-and-move-assignment-operator>`_ to mark move assignment and move construction `noexcept`.
diff --git a/docs/clang-tidy/checks/hicpp-signed-bitwise.rst b/docs/clang-tidy/checks/hicpp-signed-bitwise.rst
new file mode 100644
index 0000000..59b19b6
--- /dev/null
+++ b/docs/clang-tidy/checks/hicpp-signed-bitwise.rst
@@ -0,0 +1,9 @@
+.. title:: clang-tidy - hicpp-signed-bitwise
+
+hicpp-signed-bitwise
+====================
+
+Finds uses of bitwise operations on signed integer types, which may lead to 
+undefined or implementation defined behaviour.
+
+The according rule is defined in the `High Integrity C++ Standard, Section 5.6.1 <http://www.codingstandard.com/section/5-6-shift-operators/>`_.
diff --git a/docs/clang-tidy/checks/hicpp-special-member-functions.rst b/docs/clang-tidy/checks/hicpp-special-member-functions.rst
index b50c934..4173177 100644
--- a/docs/clang-tidy/checks/hicpp-special-member-functions.rst
+++ b/docs/clang-tidy/checks/hicpp-special-member-functions.rst
@@ -1,7 +1,9 @@
 .. title:: clang-tidy - hicpp-special-member-functions
+.. meta::
+   :http-equiv=refresh: 5;URL=cppcoreguidelines-special-member-functions.html
 
 hicpp-special-member-functions
 ==============================
 
-This check is an alias for `cppcoreguidelines-special-member-functions <cppcoreguidelines-special-member-functions.hml>`_.
+This check is an alias for `cppcoreguidelines-special-member-functions <cppcoreguidelines-special-member-functions.html>`_.
 Checks that special member functions have the correct signature, according to `rule 12.5.7 <http://www.codingstandard.com/rule/12-5-7-declare-assignment-operators-with-the-ref-qualifier/>`_.
diff --git a/docs/clang-tidy/checks/hicpp-static-assert.rst b/docs/clang-tidy/checks/hicpp-static-assert.rst
new file mode 100644
index 0000000..b5d4e41
--- /dev/null
+++ b/docs/clang-tidy/checks/hicpp-static-assert.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - hicpp-static-assert
+.. meta::
+   :http-equiv=refresh: 5;URL=misc-static-assert.html
+
+hicpp-static-assert
+===================
+
+The `hicpp-static-assert` check is an alias, please see
+`misc-static-assert <misc-static-assert.html>`_ for more information.
+It enforces the `rule 7.1.10 <http://www.codingstandard.com/rule/6-1-1-enclose-the-body-of-a-selection-or-an-iteration-statement-in-a-compound-statement/>`_.
diff --git a/docs/clang-tidy/checks/hicpp-undelegated-constructor.rst b/docs/clang-tidy/checks/hicpp-undelegated-constructor.rst
index d05d762..730a306 100644
--- a/docs/clang-tidy/checks/hicpp-undelegated-constructor.rst
+++ b/docs/clang-tidy/checks/hicpp-undelegated-constructor.rst
@@ -1,9 +1,11 @@
 .. title:: clang-tidy - hicpp-undelegated-construtor
+.. meta::
+   :http-equiv=refresh: 5;URL=misc-undelegated-constructor.html
 
 hicpp-undelegated-constructor
 =============================
 
-This check is an alias for `misc-undelegated-constructor <misc-undelegated-constructor.hml>`_.
+This check is an alias for `misc-undelegated-constructor <misc-undelegated-constructor.html>`_.
 Partially implements `rule 12.4.5 <http://www.codingstandard.com/rule/12-4-5-use-delegating-constructors-to-reduce-code-duplication/>`_ 
 to find misplaced constructor calls inside a constructor.
 
diff --git a/docs/clang-tidy/checks/hicpp-use-auto.rst b/docs/clang-tidy/checks/hicpp-use-auto.rst
new file mode 100644
index 0000000..23d0067
--- /dev/null
+++ b/docs/clang-tidy/checks/hicpp-use-auto.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - hicpp-use-auto
+.. meta::
+   :http-equiv=refresh: 5;URL=modernize-use-auto.html
+
+hicpp-use-auto
+==============
+
+The `hicpp-use-auto` check is an alias, please see
+`modernize-use-auto <modernize-use-auto.html>`_ for more information.
+It enforces the `rule 7.1.8 <http://www.codingstandard.com/rule/7-1-8-use-auto-id-expr-when-declaring-a-variable-to-have-the-same-type-as-its-initializer-function-call/>`_.
diff --git a/docs/clang-tidy/checks/hicpp-use-emplace.rst b/docs/clang-tidy/checks/hicpp-use-emplace.rst
new file mode 100644
index 0000000..07853c8
--- /dev/null
+++ b/docs/clang-tidy/checks/hicpp-use-emplace.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - hicpp-use-emplace
+.. meta::
+   :http-equiv=refresh: 5;URL=modernize-use-emplace.html
+
+hicpp-use-emplace
+=================
+
+The `hicpp-use-emplace` check is an alias, please see
+`modernize-use-emplace <modernize-use-emplace.html>`_ for more information.
+It enforces the `rule 17.4.2 <http://www.codingstandard.com/rule/17-4-2-use-api-calls-that-construct-objects-in-place/>`_.
diff --git a/docs/clang-tidy/checks/hicpp-use-equals-default.rst b/docs/clang-tidy/checks/hicpp-use-equals-default.rst
index 380ecfc..1dcf581 100644
--- a/docs/clang-tidy/checks/hicpp-use-equals-default.rst
+++ b/docs/clang-tidy/checks/hicpp-use-equals-default.rst
@@ -1,7 +1,9 @@
 .. title:: clang-tidy - hicpp-use-equals-defaults
+.. meta::
+   :http-equiv=refresh: 5;URL=modernize-use-equals-default.html
 
 hicpp-use-equals-default
 ========================
 
-This check is an alias for `modernize-use-equals-default <modernize-use-equals-default.hml>`_.
+This check is an alias for `modernize-use-equals-default <modernize-use-equals-default.html>`_.
 Implements `rule 12.5.1 <http://www.codingstandard.com/rule/12-5-1-define-explicitly-default-or-delete-implicit-special-member-functions-of-concrete-classes/>`_ to explicitly default special member functions.
diff --git a/docs/clang-tidy/checks/hicpp-use-equals-delete.rst b/docs/clang-tidy/checks/hicpp-use-equals-delete.rst
index c05da23..4d98786 100644
--- a/docs/clang-tidy/checks/hicpp-use-equals-delete.rst
+++ b/docs/clang-tidy/checks/hicpp-use-equals-delete.rst
@@ -1,8 +1,10 @@
 .. title:: clang-tidy - hicpp-use-equals-delete
+.. meta::
+   :http-equiv=refresh: 5;URL=modernize-use-equals-delete.html
 
 hicpp-use-equals-delete
 =======================
 
-This check is an alias for `modernize-use-equals-delete <modernize-use-equals-delete.hml>`_.
+This check is an alias for `modernize-use-equals-delete <modernize-use-equals-delete.html>`_.
 Implements `rule 12.5.1 <http://www.codingstandard.com/rule/12-5-1-define-explicitly-default-or-delete-implicit-special-member-functions-of-concrete-classes/>`_ 
 to explicitly default or delete special member functions.
diff --git a/docs/clang-tidy/checks/hicpp-use-noexcept.rst b/docs/clang-tidy/checks/hicpp-use-noexcept.rst
new file mode 100644
index 0000000..1a30ddf
--- /dev/null
+++ b/docs/clang-tidy/checks/hicpp-use-noexcept.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - hicpp-use-noexcept
+.. meta::
+   :http-equiv=refresh: 5;URL=modernize-use-noexcept.html
+
+hicpp-use-noexcept
+==================
+
+The `hicpp-use-noexcept` check is an alias, please see
+`modernize-use-noexcept <modernize-use-noexcept.html>`_ for more information.
+It enforces the `rule 1.3.5 <http://www.codingstandard.com/rule/1-3-5-do-not-use-throw-exception-specifications/>`_.
diff --git a/docs/clang-tidy/checks/hicpp-use-nullptr.rst b/docs/clang-tidy/checks/hicpp-use-nullptr.rst
new file mode 100644
index 0000000..9bd9051
--- /dev/null
+++ b/docs/clang-tidy/checks/hicpp-use-nullptr.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - hicpp-use-nullptr
+.. meta::
+   :http-equiv=refresh: 5;URL=modernize-use-nullptr.html
+
+hicpp-use-nullptr
+=================
+
+The `hicpp-use-nullptr` check is an alias, please see
+`modernize-use-nullptr <modernize-use-nullptr.html>`_ for more information.
+It enforces the `rule 2.5.3 <http://www.codingstandard.com/rule/2-5-3-use-nullptr-for-the-null-pointer-constant/>`_.
diff --git a/docs/clang-tidy/checks/hicpp-use-override.rst b/docs/clang-tidy/checks/hicpp-use-override.rst
index fa1f158..62541fa 100644
--- a/docs/clang-tidy/checks/hicpp-use-override.rst
+++ b/docs/clang-tidy/checks/hicpp-use-override.rst
@@ -1,8 +1,10 @@
 .. title:: clang-tidy - hicpp-use-override
+.. meta::
+   :http-equiv=refresh: 5;URL=modernize-use-override.html
 
 hicpp-use-override
 ==================
 
-This check is an alias for `modernize-use-override <modernize-use-override.hml>`_.
+This check is an alias for `modernize-use-override <modernize-use-override.html>`_.
 Implements `rule 10.2.1 <http://www.codingstandard.com/section/10-2-virtual-functions/>`_ to 
 declare a virtual function `override` when overriding.
diff --git a/docs/clang-tidy/checks/hicpp-vararg.rst b/docs/clang-tidy/checks/hicpp-vararg.rst
new file mode 100644
index 0000000..92562e4
--- /dev/null
+++ b/docs/clang-tidy/checks/hicpp-vararg.rst
@@ -0,0 +1,11 @@
+.. title:: clang-tidy - hicpp-vararg
+.. meta::
+   :http-equiv=refresh: 5;URL=cppcoreguidelines-pro-type-vararg.html
+
+hicpp-vararg
+============
+
+The `hicpp-vararg` check is an alias, please see
+`cppcoreguidelines-pro-type-vararg <cppcoreguidelines-pro-type-vararg.html>`_
+for more information.
+It enforces the `rule 14.1.1 <http://www.codingstandard.com/section/14-1-template-declarations/>`_.
diff --git a/docs/clang-tidy/checks/list.rst b/docs/clang-tidy/checks/list.rst
index f1a2839..ca3d081 100644
--- a/docs/clang-tidy/checks/list.rst
+++ b/docs/clang-tidy/checks/list.rst
@@ -4,7 +4,22 @@
 =================
 
 .. toctree::
+   android-cloexec-accept
+   android-cloexec-accept4
+   android-cloexec-creat
+   android-cloexec-epoll-create
+   android-cloexec-epoll-create1
+   android-cloexec-dup
+   android-cloexec-fopen
+   android-cloexec-inotify-init
+   android-cloexec-inotify-init1
+   android-cloexec-memfd-create
+   android-cloexec-open
+   android-cloexec-socket
    boost-use-to-string
+   bugprone-integer-division
+   bugprone-suspicious-memset-usage
+   bugprone-undefined-memory-manipulation
    cert-dcl03-c (redirects to misc-static-assert) <cert-dcl03-c>
    cert-dcl21-cpp
    cert-dcl50-cpp
@@ -23,8 +38,10 @@
    cert-msc30-c (redirects to cert-msc50-cpp) <cert-msc30-c>
    cert-msc50-cpp
    cert-oop11-cpp (redirects to misc-move-constructor-init) <cert-oop11-cpp>
+   cppcoreguidelines-c-copy-assignment-signature
    cppcoreguidelines-interfaces-global-init
    cppcoreguidelines-no-malloc
+   cppcoreguidelines-owning-memory
    cppcoreguidelines-pro-bounds-array-to-pointer-decay
    cppcoreguidelines-pro-bounds-constant-array-index
    cppcoreguidelines-pro-bounds-pointer-arithmetic
@@ -51,22 +68,34 @@
    google-readability-todo
    google-runtime-int
    google-runtime-member-string-references
-   google-runtime-memset
    google-runtime-operator
    google-runtime-references
-   hicpp-explicit-conversions
-   hicpp-function-size
-   hicpp-invalid-access-moved
-   hicpp-member-init
-   hicpp-named-parameter
-   hicpp-new-delete-operators
+   hicpp-braces-around-statements (redirects to readability-braces-around-statements) <hicpp-braces-around-statements>
+   hicpp-deprecated-headers (redirects to modernize-deprecated-headers) <hicpp-deprecated-headers>
+   hicpp-exception-baseclass
+   hicpp-explicit-conversions (redirects to google-explicit-constructor) <hicpp-explicit-conversions>
+   hicpp-function-size (redirects to readability-function-size) <hicpp-function-size>
+   hicpp-invalid-access-moved (redirects to misc-use-after-move) <hicpp-invalid-access-moved>
+   hicpp-move-const-arg (redirects to misc-move-const-arg) <hicpp-move-const-arg>
+   hicpp-member-init (redirects to cppcoreguidelines-pro-type-member-init) <hicpp-member-init>
+   hicpp-named-parameter (redirects to readability-named-parameter) <hicpp-named-parameter>
+   hicpp-new-delete-operators (redirects to misc-new-delete-overloads) <hicpp-new-delete-operators>
+   hicpp-no-array-decay (redirects to cppcoreguidelines-pro-bounds-array-to-pointer-decay) <hicpp-no-array-decay>
    hicpp-no-assembler
-   hicpp-noexcept-move
-   hicpp-special-member-functions
-   hicpp-undelegated-constructor
-   hicpp-use-equals-default
-   hicpp-use-equals-delete
-   hicpp-use-override
+   hicpp-no-malloc (redirects to cppcoreguidelines-no-malloc) <hicpp-no-malloc>
+   hicpp-noexcept-move (redirects to misc-noexcept-moveconstructor) <hicpp-noexcept-move>
+   hicpp-signed-bitwise
+   hicpp-special-member-functions (redirects to cppcoreguidelines-special-member-functions) <hicpp-special-member-functions>
+   hicpp-static-assert (redirects to misc-static-assert) <hicpp-static-assert>
+   hicpp-undelegated-constructor (redirects to misc-undelegated-constructor) <hicpp-undelegated-constructor>
+   hicpp-use-auto (redirects to modernize-use-auto) <hicpp-use-auto>
+   hicpp-use-emplace (redirects to modernize-use-emplace) <hicpp-use-emplace>
+   hicpp-use-equals-default (redirects to modernize-use-equals-default) <hicpp-use-equals-default>
+   hicpp-use-equals-delete (redirects to modernize-use-equals-delete) <hicpp-use-equals-delete>
+   hicpp-use-noexcept (redirects to modernize-use-noexcept) <hicpp-use-noexcept>
+   hicpp-use-nullptr (redirects to modernize-use-nullptr) <hicpp-use-nullptr>
+   hicpp-use-override (redirects to modernize-use-override) <hicpp-use-override>
+   hicpp-vararg (redirects to cppcoreguidelines-pro-type-varg) <hicpp-vararg>
    llvm-header-guard
    llvm-include-order
    llvm-namespace-comment
@@ -129,6 +158,7 @@
    modernize-replace-random-shuffle
    modernize-return-braced-init-list
    modernize-shrink-to-fit
+   modernize-unary-static-assert
    modernize-use-auto
    modernize-use-bool-literals
    modernize-use-default-member-init
@@ -144,7 +174,7 @@
    mpi-type-mismatch
    performance-faster-string-find
    performance-for-range-copy
-   performance-implicit-cast-in-loop
+   performance-implicit-conversion-in-loop
    performance-inefficient-string-concatenation
    performance-inefficient-vector-operation
    performance-type-promotion-in-math-fn
@@ -158,7 +188,7 @@
    readability-else-after-return
    readability-function-size
    readability-identifier-naming
-   readability-implicit-bool-cast
+   readability-implicit-bool-conversion
    readability-inconsistent-declaration-parameter-name
    readability-misleading-indentation
    readability-misplaced-array-index
@@ -172,5 +202,6 @@
    readability-redundant-string-cstr
    readability-redundant-string-init
    readability-simplify-boolean-expr
+   readability-static-accessed-through-instance
    readability-static-definition-in-anonymous-namespace
    readability-uniqueptr-delete-release
diff --git a/docs/clang-tidy/checks/misc-definitions-in-headers.rst b/docs/clang-tidy/checks/misc-definitions-in-headers.rst
index 32e7b5e..96a3b1b 100644
--- a/docs/clang-tidy/checks/misc-definitions-in-headers.rst
+++ b/docs/clang-tidy/checks/misc-definitions-in-headers.rst
@@ -74,6 +74,16 @@
    template <typename T>
    void B<T>::f1() {}
 
+   class CE {
+     constexpr static int i = 5; // OK: inline variable definition.
+   };
+
+   inline int i = 5; // OK: inline variable definition.
+
+   constexpr int k = 1; // OK: constexpr variable has internal linkage.
+
+   constexpr int f10() { return 0; } // OK: constexpr function definition.
+
 Options
 -------
 
diff --git a/docs/clang-tidy/checks/misc-forwarding-reference-overload.rst b/docs/clang-tidy/checks/misc-forwarding-reference-overload.rst
index 434c681..1682a5f 100644
--- a/docs/clang-tidy/checks/misc-forwarding-reference-overload.rst
+++ b/docs/clang-tidy/checks/misc-forwarding-reference-overload.rst
@@ -4,7 +4,7 @@
 ==================================
 
 The check looks for perfect forwarding constructors that can hide copy or move
-constructors. If a non const lvalue reference is passed to the constructor, the 
+constructors. If a non const lvalue reference is passed to the constructor, the
 forwarding reference parameter will be a better match than the const reference
 parameter of the copy constructor, so the perfect forwarding constructor will be
 called, which can be confusing.
@@ -14,7 +14,7 @@
 Consider the following example:
 
   .. code-block:: c++
-  
+
     class Person {
     public:
       // C1: perfect forwarding ctor
@@ -24,15 +24,15 @@
       // C2: perfect forwarding ctor with parameter default value
       template<typename T>
       explicit Person(T&& n, int x = 1) {}
-      
+
       // C3: perfect forwarding ctor guarded with enable_if
       template<typename T, typename X = enable_if_t<is_special<T>,void>>
       explicit Person(T&& n) {}
-      
+
       // (possibly compiler generated) copy ctor
-      Person(const Person& rhs); 
+      Person(const Person& rhs);
     };
-    
+
 The check warns for constructors C1 and C2, because those can hide copy and move
 constructors. We suppress warnings if the copy and the move constructors are both
 disabled (deleted or private), because there is nothing the perfect forwarding
@@ -44,6 +44,6 @@
 ----------
 
 For deciding whether a constructor is guarded with enable_if, we consider the
-default values of the type parameters and the types of the contructor
+default values of the type parameters and the types of the constructor
 parameters. If any part of these types is std::enable_if or std::enable_if_t, we
 assume the constructor is guarded.
diff --git a/docs/clang-tidy/checks/misc-string-constructor.rst b/docs/clang-tidy/checks/misc-string-constructor.rst
index a5d2c88..a4f3920 100644
--- a/docs/clang-tidy/checks/misc-string-constructor.rst
+++ b/docs/clang-tidy/checks/misc-string-constructor.rst
@@ -11,7 +11,7 @@
 
 .. code-block:: c++
 
-  std::string('x', 50) str; // should be std::string(50, 'x')
+  std::string str('x', 50); // should be str(50, 'x')
 
 Calling the string-literal constructor with a length bigger than the literal is
 suspicious and adds extra random characters to the string.
diff --git a/docs/clang-tidy/checks/modernize-make-shared.rst b/docs/clang-tidy/checks/modernize-make-shared.rst
index d33d3b1..e73b320 100644
--- a/docs/clang-tidy/checks/modernize-make-shared.rst
+++ b/docs/clang-tidy/checks/modernize-make-shared.rst
@@ -25,3 +25,26 @@
   // becomes
 
   my_ptr = std::make_shared<MyPair>(1, 2);
+
+Options
+-------
+
+.. option:: MakeSmartPtrFunction
+
+   A string specifying the name of make-shared-ptr function. Default is
+   `std::make_shared`.
+
+.. option:: MakeSmartPtrFunctionHeader
+
+   A string specifying the corresponding header of make-shared-ptr function.
+   Default is `memory`.
+
+.. option:: IncludeStyle
+
+   A string specifying which include-style is used, `llvm` or `google`. Default
+   is `llvm`.
+
+.. option:: IgnoreMacros
+
+   If set to non-zero, the check will not give warnings inside macros. Default
+   is `1`.
diff --git a/docs/clang-tidy/checks/modernize-make-unique.rst b/docs/clang-tidy/checks/modernize-make-unique.rst
index 0dce521..1961f05 100644
--- a/docs/clang-tidy/checks/modernize-make-unique.rst
+++ b/docs/clang-tidy/checks/modernize-make-unique.rst
@@ -25,3 +25,26 @@
   // becomes
 
   my_ptr = std::make_unique<MyPair>(1, 2);
+
+Options
+-------
+
+.. option:: MakeSmartPtrFunction
+
+   A string specifying the name of make-unique-ptr function. Default is
+   `std::make_unique`.
+
+.. option:: MakeSmartPtrFunctionHeader
+
+   A string specifying the corresponding header of make-unique-ptr function.
+   Default is `memory`.
+
+.. option:: IncludeStyle
+
+   A string specifying which include-style is used, `llvm` or `google`. Default
+   is `llvm`.
+
+.. option:: IgnoreMacros
+
+   If set to non-zero, the check will not give warnings inside macros. Default
+   is `1`.
diff --git a/docs/clang-tidy/checks/modernize-replace-random-shuffle.rst b/docs/clang-tidy/checks/modernize-replace-random-shuffle.rst
index b0c2cd5..353f35a 100644
--- a/docs/clang-tidy/checks/modernize-replace-random-shuffle.rst
+++ b/docs/clang-tidy/checks/modernize-replace-random-shuffle.rst
@@ -15,7 +15,7 @@
   std::random_shuffle(vec.begin(), vec.end());
 
   // Second example
-  std::random_shuffle(vec.begin(), vec.end(), randomFun);
+  std::random_shuffle(vec.begin(), vec.end(), randomFunc);
 
 Both of these examples will be replaced with:
 
diff --git a/docs/clang-tidy/checks/modernize-unary-static-assert.rst b/docs/clang-tidy/checks/modernize-unary-static-assert.rst
new file mode 100644
index 0000000..31ece10
--- /dev/null
+++ b/docs/clang-tidy/checks/modernize-unary-static-assert.rst
@@ -0,0 +1,25 @@
+.. title:: clang-tidy - modernize-unary-static-assert
+
+modernize-unary-static-assert
+=============================
+
+The check diagnoses any ``static_assert`` declaration with an empty string literal
+and provides a fix-it to replace the declaration with a single-argument ``static_assert`` declaration.
+
+The check is only applicable for C++17 and later code.
+
+The following code:
+
+.. code-block:: c++
+
+  void f_textless(int a) {
+    static_assert(sizeof(a) <= 10, "");
+  }
+
+is replaced by:
+
+.. code-block:: c++
+
+  void f_textless(int a) {
+    static_assert(sizeof(a) <= 10);
+  }
diff --git a/docs/clang-tidy/checks/modernize-use-bool-literals.rst b/docs/clang-tidy/checks/modernize-use-bool-literals.rst
index 7ce048f..792d3a4 100644
--- a/docs/clang-tidy/checks/modernize-use-bool-literals.rst
+++ b/docs/clang-tidy/checks/modernize-use-bool-literals.rst
@@ -18,3 +18,11 @@
   bool f = true;
   std::ios_base::sync_with_stdio(false);
   bool x = p ? true : false;
+
+Options
+-------
+
+.. option:: IgnoreMacros
+
+   If set to non-zero, the check will not give warnings inside macros. Default
+   is `1`.
diff --git a/docs/clang-tidy/checks/modernize-use-emplace.rst b/docs/clang-tidy/checks/modernize-use-emplace.rst
index dee79ab..533125e 100644
--- a/docs/clang-tidy/checks/modernize-use-emplace.rst
+++ b/docs/clang-tidy/checks/modernize-use-emplace.rst
@@ -102,6 +102,18 @@
    Semicolon-separated list of class names of custom containers that support
    ``push_back``.
 
+.. option:: IgnoreImplicitConstructors
+
+    When non-zero, the check will ignore implicitly constructed arguments of
+    ``push_back``, e.g.
+
+    .. code-block:: c++
+
+        std::vector<std::string> v;
+        v.push_back("a"); // Ignored when IgnoreImplicitConstructors is ``1``.
+
+    Default is ``0``.
+
 .. option:: SmartPointers
 
    Semicolon-separated list of class names of custom smart pointers.
diff --git a/docs/clang-tidy/checks/modernize-use-equals-default.rst b/docs/clang-tidy/checks/modernize-use-equals-default.rst
index b87f883..4b2368c 100644
--- a/docs/clang-tidy/checks/modernize-use-equals-default.rst
+++ b/docs/clang-tidy/checks/modernize-use-equals-default.rst
@@ -26,3 +26,11 @@
 
 .. note::
   Move-constructor and move-assignment operator are not supported yet.
+
+Options
+-------
+
+.. option:: IgnoreMacros
+
+   If set to non-zero, the check will not give warnings inside macros. Default
+   is `1`.
diff --git a/docs/clang-tidy/checks/modernize-use-using.rst b/docs/clang-tidy/checks/modernize-use-using.rst
index 14172bb..1456a91 100644
--- a/docs/clang-tidy/checks/modernize-use-using.rst
+++ b/docs/clang-tidy/checks/modernize-use-using.rst
@@ -24,3 +24,11 @@
   using MyPtrType = void (Class::*)() const;
 
 This check requires using C++11 or higher to run.
+
+Options
+-------
+
+.. option:: IgnoreMacros
+
+   If set to non-zero, the check will not give warnings inside macros. Default
+   is `1`.
diff --git a/docs/clang-tidy/checks/performance-implicit-cast-in-loop.rst b/docs/clang-tidy/checks/performance-implicit-cast-in-loop.rst
index 7a5cdf4..280e7c0 100644
--- a/docs/clang-tidy/checks/performance-implicit-cast-in-loop.rst
+++ b/docs/clang-tidy/checks/performance-implicit-cast-in-loop.rst
@@ -1,21 +1,12 @@
+:orphan:
+
 .. title:: clang-tidy - performance-implicit-cast-in-loop
+.. meta::
+   :http-equiv=refresh: 5;URL=performance-implicit-conversion-in-loop.html
 
 performance-implicit-cast-in-loop
 =================================
 
-This warning appears in a range-based loop with a loop variable of const ref
-type where the type of the variable does not match the one returned by the
-iterator. This means that an implicit cast has been added, which can for example
-result in expensive deep copies.
+This check has been renamed to `performance-implicit-conversion-in-loop
+<performance-implicit-conversion-in-loop.html>`_.
 
-Example:
-
-.. code-block:: c++
-
-  map<int, vector<string>> my_map;
-  for (const pair<int, vector<string>>& p : my_map) {}
-  // The iterator type is in fact pair<const int, vector<string>>, which means
-  // that the compiler added a cast, resulting in a copy of the vectors.
-
-The easiest solution is usually to use ``const auto&`` instead of writing the type
-manually.
diff --git a/docs/clang-tidy/checks/performance-implicit-conversion-in-loop.rst b/docs/clang-tidy/checks/performance-implicit-conversion-in-loop.rst
new file mode 100644
index 0000000..14e4d31
--- /dev/null
+++ b/docs/clang-tidy/checks/performance-implicit-conversion-in-loop.rst
@@ -0,0 +1,21 @@
+.. title:: clang-tidy - performance-implicit-conversion-in-loop
+
+performance-implicit-conversion-in-loop
+=======================================
+
+This warning appears in a range-based loop with a loop variable of const ref
+type where the type of the variable does not match the one returned by the
+iterator. This means that an implicit conversion happens, which can for example
+result in expensive deep copies.
+
+Example:
+
+.. code-block:: c++
+
+  map<int, vector<string>> my_map;
+  for (const pair<int, vector<string>>& p : my_map) {}
+  // The iterator type is in fact pair<const int, vector<string>>, which means
+  // that the compiler added a conversion, resulting in a copy of the vectors.
+
+The easiest solution is usually to use ``const auto&`` instead of writing the
+type manually.
diff --git a/docs/clang-tidy/checks/performance-inefficient-vector-operation.rst b/docs/clang-tidy/checks/performance-inefficient-vector-operation.rst
index d6288b9..8cf9318 100644
--- a/docs/clang-tidy/checks/performance-inefficient-vector-operation.rst
+++ b/docs/clang-tidy/checks/performance-inefficient-vector-operation.rst
@@ -18,7 +18,7 @@
     v.push_back(n);
     // This will trigger the warning since the push_back may cause multiple
     // memory reallocations in v. This can be avoid by inserting a 'reserve(n)'
-    // statment before the for statment.
+    // statement before the for statement.
   }
 
 
@@ -36,7 +36,7 @@
     v.push_back(element);
     // This will trigger the warning since the 'push_back' may cause multiple
     // memory reallocations in v. This can be avoid by inserting a
-    // 'reserve(data.size())' statment before the for statment.
+    // 'reserve(data.size())' statement before the for statement.
   }
 
 
diff --git a/docs/clang-tidy/checks/readability-implicit-bool-cast.rst b/docs/clang-tidy/checks/readability-implicit-bool-cast.rst
index bcd23ab..a6a3492 100644
--- a/docs/clang-tidy/checks/readability-implicit-bool-cast.rst
+++ b/docs/clang-tidy/checks/readability-implicit-bool-cast.rst
@@ -1,130 +1,11 @@
+:orphan:
+
 .. title:: clang-tidy - readability-implicit-bool-cast
+.. meta::
+   :http-equiv=refresh: 5;URL=readability-implicit-bool-conversion.html
 
 readability-implicit-bool-cast
 ==============================
 
-This check can be used to find implicit conversions between built-in types and
-booleans. Depending on use case, it may simply help with readability of the code,
-or in some cases, point to potential bugs which remain unnoticed due to implicit
-conversions.
-
-The following is a real-world example of bug which was hiding behind implicit
-``bool`` cast:
-
-.. code-block:: c++
-
-  class Foo {
-    int m_foo;
-
-  public:
-    void setFoo(bool foo) { m_foo = foo; } // warning: implicit cast bool -> int
-    int getFoo() { return m_foo; }
-  };
-
-  void use(Foo& foo) {
-    bool value = foo.getFoo(); // warning: implicit cast int -> bool
-  }
-
-This code is the result of unsuccessful refactoring, where type of ``m_foo``
-changed from ``bool`` to ``int``. The programmer forgot to change all
-occurrences of ``bool``, and the remaining code is no longer correct, yet it
-still compiles without any visible warnings.
-
-In addition to issuing warnings, fix-it hints are provided to help solve the
-reported issues. This can be used for improving readability of code, for
-example:
-
-.. code-block:: c++
-
-  void conversionsToBool() {
-    float floating;
-    bool boolean = floating;
-    // ^ propose replacement: bool boolean = floating != 0.0f;
-
-    int integer;
-    if (integer) {}
-    // ^ propose replacement: if (integer != 0) {}
-
-    int* pointer;
-    if (!pointer) {}
-    // ^ propose replacement: if (pointer == nullptr) {}
-
-    while (1) {}
-    // ^ propose replacement: while (true) {}
-  }
-
-  void functionTakingInt(int param);
-
-  void conversionsFromBool() {
-    bool boolean;
-    functionTakingInt(boolean);
-    // ^ propose replacement: functionTakingInt(static_cast<int>(boolean));
-
-    functionTakingInt(true);
-    // ^ propose replacement: functionTakingInt(1);
-  }
-
-In general, the following cast types are checked:
-
-- integer expression/literal to boolean,
-
-- floating expression/literal to boolean,
-
-- pointer/pointer to member/``nullptr``/``NULL`` to boolean,
-
-- boolean expression/literal to integer,
-
-- boolean expression/literal to floating.
-
-The rules for generating fix-it hints are:
-
-- in case of casts from other built-in type to bool, an explicit comparison
-  is proposed to make it clear what exaclty is being compared:
-
-  - ``bool boolean = floating;`` is changed to
-    ``bool boolean = floating == 0.0f;``,
-
-  - for other types, appropriate literals are used (``0``, ``0u``, ``0.0f``,
-    ``0.0``, ``nullptr``),
-
-- in case of negated expressions cast to bool, the proposed replacement with
-  comparison is simplified:
-
-  - ``if (!pointer)`` is changed to ``if (pointer == nullptr)``,
-
-- in case of casts from bool to other built-in types, an explicit ``static_cast``
-  is proposed to make it clear that a cast is taking place:
-
-  - ``int integer = boolean;`` is changed to
-    ``int integer = static_cast<int>(boolean);``,
-
-- if the cast is performed on type literals, an equivalent literal is proposed,
-  according to what type is actually expected, for example:
-
-  - ``functionTakingBool(0);`` is changed to ``functionTakingBool(false);``,
-
-  - ``functionTakingInt(true);`` is changed to ``functionTakingInt(1);``,
-
-  - for other types, appropriate literals are used (``false``, ``true``, ``0``,
-    ``1``, ``0u``, ``1u``, ``0.0f``, ``1.0f``, ``0.0``, ``1.0f``).
-
-Some additional accommodations are made for pre-C++11 dialects:
-
-- ``false`` literal cast to pointer is detected,
-
-- instead of ``nullptr`` literal, ``0`` is proposed as replacement.
-
-Occurrences of implicit casts inside macros and template instantiations are
-deliberately ignored, as it is not clear how to deal with such cases.
-
-Options
--------
-
-.. option::  AllowConditionalIntegerCasts
-
-   When non-zero, the check will allow conditional integer casts. Default is
-   `0`.
-
-.. option::  AllowConditionalPointerCasts
-
-   When non-zero, the check will allow conditional pointer casts. Default is `0`.
+This check has been renamed to `readability-implicit-bool-conversion
+<readability-implicit-bool-conversion.html>`_.
diff --git a/docs/clang-tidy/checks/readability-implicit-bool-conversion.rst b/docs/clang-tidy/checks/readability-implicit-bool-conversion.rst
new file mode 100644
index 0000000..64f3f73
--- /dev/null
+++ b/docs/clang-tidy/checks/readability-implicit-bool-conversion.rst
@@ -0,0 +1,132 @@
+.. title:: clang-tidy - readability-implicit-bool-conversion
+
+readability-implicit-bool-conversion
+====================================
+
+This check can be used to find implicit conversions between built-in types and
+booleans. Depending on use case, it may simply help with readability of the code,
+or in some cases, point to potential bugs which remain unnoticed due to implicit
+conversions.
+
+The following is a real-world example of bug which was hiding behind implicit
+``bool`` conversion:
+
+.. code-block:: c++
+
+  class Foo {
+    int m_foo;
+
+  public:
+    void setFoo(bool foo) { m_foo = foo; } // warning: implicit conversion bool -> int
+    int getFoo() { return m_foo; }
+  };
+
+  void use(Foo& foo) {
+    bool value = foo.getFoo(); // warning: implicit conversion int -> bool
+  }
+
+This code is the result of unsuccessful refactoring, where type of ``m_foo``
+changed from ``bool`` to ``int``. The programmer forgot to change all
+occurrences of ``bool``, and the remaining code is no longer correct, yet it
+still compiles without any visible warnings.
+
+In addition to issuing warnings, fix-it hints are provided to help solve the
+reported issues. This can be used for improving readability of code, for
+example:
+
+.. code-block:: c++
+
+  void conversionsToBool() {
+    float floating;
+    bool boolean = floating;
+    // ^ propose replacement: bool boolean = floating != 0.0f;
+
+    int integer;
+    if (integer) {}
+    // ^ propose replacement: if (integer != 0) {}
+
+    int* pointer;
+    if (!pointer) {}
+    // ^ propose replacement: if (pointer == nullptr) {}
+
+    while (1) {}
+    // ^ propose replacement: while (true) {}
+  }
+
+  void functionTakingInt(int param);
+
+  void conversionsFromBool() {
+    bool boolean;
+    functionTakingInt(boolean);
+    // ^ propose replacement: functionTakingInt(static_cast<int>(boolean));
+
+    functionTakingInt(true);
+    // ^ propose replacement: functionTakingInt(1);
+  }
+
+In general, the following conversion types are checked:
+
+- integer expression/literal to boolean,
+
+- floating expression/literal to boolean,
+
+- pointer/pointer to member/``nullptr``/``NULL`` to boolean,
+
+- boolean expression/literal to integer,
+
+- boolean expression/literal to floating.
+
+The rules for generating fix-it hints are:
+
+- in case of conversions from other built-in type to bool, an explicit
+  comparison is proposed to make it clear what exaclty is being compared:
+
+  - ``bool boolean = floating;`` is changed to
+    ``bool boolean = floating == 0.0f;``,
+
+  - for other types, appropriate literals are used (``0``, ``0u``, ``0.0f``,
+    ``0.0``, ``nullptr``),
+
+- in case of negated expressions conversion to bool, the proposed replacement
+  with comparison is simplified:
+
+  - ``if (!pointer)`` is changed to ``if (pointer == nullptr)``,
+
+- in case of conversions from bool to other built-in types, an explicit
+  ``static_cast`` is proposed to make it clear that a conversion is taking
+  place:
+
+  - ``int integer = boolean;`` is changed to
+    ``int integer = static_cast<int>(boolean);``,
+
+- if the conversion is performed on type literals, an equivalent literal is
+  proposed, according to what type is actually expected, for example:
+
+  - ``functionTakingBool(0);`` is changed to ``functionTakingBool(false);``,
+
+  - ``functionTakingInt(true);`` is changed to ``functionTakingInt(1);``,
+
+  - for other types, appropriate literals are used (``false``, ``true``, ``0``,
+    ``1``, ``0u``, ``1u``, ``0.0f``, ``1.0f``, ``0.0``, ``1.0f``).
+
+Some additional accommodations are made for pre-C++11 dialects:
+
+- ``false`` literal conversion to pointer is detected,
+
+- instead of ``nullptr`` literal, ``0`` is proposed as replacement.
+
+Occurrences of implicit conversions inside macros and template instantiations
+are deliberately ignored, as it is not clear how to deal with such cases.
+
+Options
+-------
+
+.. option::  AllowIntegerConditions
+
+   When non-zero, the check will allow conditional integer conversions. Default
+   is `0`.
+
+.. option::  AllowPointerConditions
+
+   When non-zero, the check will allow conditional pointer conversions. Default
+   is `0`.
diff --git a/docs/clang-tidy/checks/readability-redundant-declaration.rst b/docs/clang-tidy/checks/readability-redundant-declaration.rst
index 4b5d0a5..8ce7aac 100644
--- a/docs/clang-tidy/checks/readability-redundant-declaration.rst
+++ b/docs/clang-tidy/checks/readability-redundant-declaration.rst
@@ -27,3 +27,11 @@
 
 * When the declarations are in different header files;
 * When multiple variables are declared together.
+
+Options
+-------
+
+.. option:: IgnoreMacros
+
+   If set to non-zero, the check will not give warnings inside macros. Default
+   is `1`.
diff --git a/docs/clang-tidy/checks/readability-static-accessed-through-instance.rst b/docs/clang-tidy/checks/readability-static-accessed-through-instance.rst
new file mode 100644
index 0000000..879b87c
--- /dev/null
+++ b/docs/clang-tidy/checks/readability-static-accessed-through-instance.rst
@@ -0,0 +1,31 @@
+.. title:: clang-tidy - readability-static-accessed-through-instance
+
+readability-static-accessed-through-instance
+============================================
+
+Checks for member expressions that access static members through instances, and
+replaces them with uses of the appropriate qualified-id.
+
+Example:
+
+The following code:
+
+.. code-block:: c++
+
+  struct C {
+    static void foo();
+    static int x;
+  };
+
+  C *c1 = new C();
+  c1->foo();
+  c1->x;
+
+is changed to:
+
+.. code-block:: c++
+
+  C *c1 = new C();
+  C::foo();
+  C::x;
+
diff --git a/docs/clang-tidy/index.rst b/docs/clang-tidy/index.rst
index 8fb70d0..69136e6 100644
--- a/docs/clang-tidy/index.rst
+++ b/docs/clang-tidy/index.rst
@@ -55,7 +55,9 @@
 ====================== =========================================================
 Name prefix            Description
 ====================== =========================================================
+``android-``           Checks related to Android.
 ``boost-``             Checks related to Boost library.
+``bugprone-``          Checks that target bugprone code constructs.
 ``cert-``              Checks related to CERT Secure Coding Guidelines.
 ``cppcoreguidelines-`` Checks related to C++ Core Guidelines.
 ``clang-analyzer-``    Clang Static Analyzer checks.
diff --git a/docs/clang-tidy/tools/dump_check_docs.py b/docs/clang-tidy/tools/dump_check_docs.py
deleted file mode 100755
index a45d15a..0000000
--- a/docs/clang-tidy/tools/dump_check_docs.py
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/usr/bin/env python
-
-r"""
-Create stubs for check documentation files.
-"""
-
-import os
-import re
-import sys
-
-def main():
-  clang_tidy_dir = os.path.normpath(
-      os.path.join(os.path.dirname(sys.argv[0]), '..', '..', '..',
-                   'clang-tidy'))
-
-  checks_doc_dir = os.path.normpath(
-      os.path.join(clang_tidy_dir, '..', 'docs', 'clang-tidy', 'checks'))
-
-  registered_checks = {}
-  defined_checks = {}
-
-  for dir_name, subdir_list, file_list in os.walk(clang_tidy_dir):
-    print('Processing directory ' + dir_name + '...')
-    for file_name in file_list:
-      full_name = os.path.join(dir_name, file_name)
-      if file_name.endswith('Module.cpp'):
-        print('Module ' + file_name)
-        with open(full_name, 'r') as f:
-          text = f.read()
-        for class_name, check_name in re.findall(
-            r'\.\s*registerCheck\s*<\s*([A-Za-z0-9:]+)\s*>\(\s*"([a-z0-9-]+)"',
-            text):
-          registered_checks[check_name] = class_name
-      elif file_name.endswith('.h'):
-        print('    ' + file_name + '...')
-        with open(full_name, 'r') as f:
-          text = f.read()
-        for comment, _, _, class_name in re.findall(
-            r'((([\r\n]//)[^\r\n]*)*)\s+class (\w+)\s*:' +
-            '\s*public\s+ClangTidyCheck\s*\{', text):
-          defined_checks[class_name] = comment
-
-  print('Registered checks [%s]: [%s]' %
-        (len(registered_checks), registered_checks))
-  print('Check implementations: %s' % len(defined_checks))
-
-  checks = registered_checks.keys()
-  checks.sort()
-
-  for check_name in checks:
-    doc_file_name = os.path.join(checks_doc_dir, check_name + '.rst')
-    #if os.path.exists(doc_file_name):
-    #  print('Skipping existing file %s...')
-    #  continue
-    print('Updating %s...' % doc_file_name)
-    with open(doc_file_name, 'w') as f:
-      class_name = re.sub(r'.*:', '', registered_checks[check_name])
-      f.write(check_name + '\n' + ('=' * len(check_name)) + '\n\n')
-      if class_name in defined_checks:
-        text = defined_checks[class_name]
-        text = re.sub(r'\n//+ ?(\\brief )?', r'\n', text)
-        text = re.sub(r'(\n *)\\code\n', r'\1.. code:: c++\n\n', text)
-        text = re.sub(r'(\n *)\\endcode(\n|$)', r'\n', text)
-        text = re.sub(r'`', r'``', text)
-        f.write(text + '\n')
-      else:
-        f.write('TODO: add docs\n')
-
-  with open(os.path.join(checks_doc_dir, 'list.rst'), 'w') as f:
-    f.write(
-r"""List of clang-tidy Checks
-=========================
-
-.. toctree::
-   """ + '\n   '.join(checks))
-
-
-if __name__ == '__main__':
-  main()
diff --git a/docs/clangd.rst b/docs/clangd.rst
index 54e68fb..d7284a2 100644
--- a/docs/clangd.rst
+++ b/docs/clangd.rst
@@ -54,7 +54,7 @@
 +-------------------------------------+------------+----------+ 
 | Fix-its                             | Yes        |   Yes    |
 +-------------------------------------+------------+----------+
-| Go to Definition                    | Yes        |   No     |
+| Go to Definition                    | Yes        |   Yes    |
 +-------------------------------------+------------+----------+
 | Source hover                        | Yes        |   No     |
 +-------------------------------------+------------+----------+
@@ -103,4 +103,4 @@
 to the `Language Server Protocol
 <https://github.com/Microsoft/language-server-protocol>`_ itself would also be
 very useful, so that :program:`Clangd` can eventually implement them in a
-conforming way.
\ No newline at end of file
+conforming way.
diff --git a/docs/conf.py b/docs/conf.py
index e872c55..6f3a201 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -49,9 +49,9 @@
 # built documents.
 #
 # The short version.
-version = '5'
+version = '6'
 # The full version, including alpha/beta/rc tags.
-release = '5'
+release = '6'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/include-fixer/find-all-symbols/FindAllSymbols.cpp b/include-fixer/find-all-symbols/FindAllSymbols.cpp
index cf8ce4e..bd5032d 100644
--- a/include-fixer/find-all-symbols/FindAllSymbols.cpp
+++ b/include-fixer/find-all-symbols/FindAllSymbols.cpp
@@ -230,7 +230,8 @@
   MatchFinder->addMatcher(
       typeLoc(isExpansionInMainFile(),
               loc(templateSpecializationType(hasDeclaration(
-                  classTemplateDecl(has(CXXRecords.bind("use"))))))),
+                  classTemplateSpecializationDecl(hasSpecializedTemplate(
+                      classTemplateDecl(has(CXXRecords.bind("use"))))))))),
       this);
 }
 
diff --git a/include-fixer/find-all-symbols/SymbolInfo.cpp b/include-fixer/find-all-symbols/SymbolInfo.cpp
index a219539..00bfbe5 100644
--- a/include-fixer/find-all-symbols/SymbolInfo.cpp
+++ b/include-fixer/find-all-symbols/SymbolInfo.cpp
@@ -22,7 +22,6 @@
 using SymbolKind = clang::find_all_symbols::SymbolInfo::SymbolKind;
 
 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(SymbolAndSignals)
-LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(std::string)
 LLVM_YAML_IS_SEQUENCE_VECTOR(SymbolInfo::Context)
 
 namespace llvm {
diff --git a/include-fixer/tool/ClangIncludeFixer.cpp b/include-fixer/tool/ClangIncludeFixer.cpp
index 9db129c..2f2e45e 100644
--- a/include-fixer/tool/ClangIncludeFixer.cpp
+++ b/include-fixer/tool/ClangIncludeFixer.cpp
@@ -28,7 +28,6 @@
 using clang::include_fixer::IncludeFixerContext;
 
 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(IncludeFixerContext)
-LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(std::string)
 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(IncludeFixerContext::HeaderInfo)
 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(IncludeFixerContext::QuerySymbolInfo)
 
diff --git a/include-fixer/tool/clang-include-fixer.el b/include-fixer/tool/clang-include-fixer.el
index f704b30..ab10002 100644
--- a/include-fixer/tool/clang-include-fixer.el
+++ b/include-fixer/tool/clang-include-fixer.el
@@ -58,6 +58,7 @@
 (defface clang-include-fixer-highlight '((t :background "green"))
   "Used for highlighting the symbol for which a header file is being added.")
 
+;;;###autoload
 (defun clang-include-fixer ()
   "Invoke the Include Fixer to insert missing C++ headers."
   (interactive)
@@ -66,6 +67,7 @@
   (clang-include-fixer--start #'clang-include-fixer--add-header
                               "-output-headers"))
 
+;;;###autoload
 (defun clang-include-fixer-at-point ()
   "Invoke the Clang include fixer for the symbol at point."
   (interactive)
@@ -74,6 +76,7 @@
       (user-error "No symbol at current location"))
     (clang-include-fixer-from-symbol symbol)))
 
+;;;###autoload
 (defun clang-include-fixer-from-symbol (symbol)
   "Invoke the Clang include fixer for the SYMBOL.
 When called interactively, prompts the user for a symbol."
@@ -88,6 +91,8 @@
 the call was successful the returned result is stored in a
 temporary buffer, and CALLBACK is called with the temporary
 buffer as only argument."
+  (unless buffer-file-name
+    (user-error "clang-include-fixer works only in buffers that visit a file"))
   (let ((process (if (fboundp 'make-process)
                      ;; Prefer using ‘make-process’ if available, because
                      ;; ‘start-process’ doesn’t allow us to separate the
@@ -185,9 +190,9 @@
   "Replace current buffer by content of STDOUT."
   (cl-check-type stdout buffer-live)
   (barf-if-buffer-read-only)
-  (unless (clang-include-fixer--insert-line stdout (current-buffer))
-    (erase-buffer)
-    (insert-buffer-substring stdout))
+  (cond ((fboundp 'replace-buffer-contents) (replace-buffer-contents stdout))
+        ((clang-include-fixer--insert-line stdout (current-buffer)))
+        (t (erase-buffer) (insert-buffer-substring stdout)))
   (message "Fix applied")
   nil)
 
diff --git a/modularize/CMakeLists.txt b/modularize/CMakeLists.txt
index 17d1eb1..187db94 100644
--- a/modularize/CMakeLists.txt
+++ b/modularize/CMakeLists.txt
@@ -3,7 +3,7 @@
   Support
   )
 
-add_clang_executable(modularize
+add_clang_tool(modularize
   Modularize.cpp
   ModuleAssistant.cpp
   ModularizeUtilities.cpp
diff --git a/modularize/CoverageChecker.cpp b/modularize/CoverageChecker.cpp
index 510d062..3687872 100644
--- a/modularize/CoverageChecker.cpp
+++ b/modularize/CoverageChecker.cpp
@@ -242,14 +242,15 @@
     Directory = ".";
   // Walk the directory.
   std::error_code EC;
-  sys::fs::file_status Status;
   for (sys::fs::directory_iterator I(Directory.str(), EC), E; I != E;
     I.increment(EC)) {
     if (EC)
       return false;
     std::string File(I->path());
-    I->status(Status);
-    sys::fs::file_type Type = Status.type();
+    llvm::ErrorOr<sys::fs::basic_file_status> Status = I->status();
+    if (!Status)
+      return false;
+    sys::fs::file_type Type = Status->type();
     // If the file is a directory, ignore the name and recurse.
     if (Type == sys::fs::file_type::directory_file) {
       if (!collectUmbrellaHeaders(File))
@@ -363,7 +364,6 @@
 
   // Recursively walk the directory tree.
   std::error_code EC;
-  sys::fs::file_status Status;
   int Count = 0;
   for (sys::fs::recursive_directory_iterator I(Directory.str(), EC), E; I != E;
     I.increment(EC)) {
@@ -371,8 +371,10 @@
       return false;
     //std::string file(I->path());
     StringRef file(I->path());
-    I->status(Status);
-    sys::fs::file_type type = Status.type();
+    llvm::ErrorOr<sys::fs::basic_file_status> Status = I->status();
+    if (!Status)
+      return false;
+    sys::fs::file_type type = Status->type();
     // If the file is a directory, ignore the name (but still recurses).
     if (type == sys::fs::file_type::directory_file)
       continue;
diff --git a/modularize/Modularize.cpp b/modularize/Modularize.cpp
index 83f2340..e5f19de 100644
--- a/modularize/Modularize.cpp
+++ b/modularize/Modularize.cpp
@@ -825,7 +825,7 @@
   // No go if we have no header list file.
   if (ListFileNames.size() == 0) {
     cl::PrintHelpMessage();
-    return 1;
+    return 0;
   }
 
   std::unique_ptr<ModularizeUtilities> ModUtil;
diff --git a/modularize/ModularizeUtilities.cpp b/modularize/ModularizeUtilities.cpp
index 874742d..85768d5 100644
--- a/modularize/ModularizeUtilities.cpp
+++ b/modularize/ModularizeUtilities.cpp
@@ -399,14 +399,15 @@
   SmallString<256> Directory(UmbrellaDirName);
   // Walk the directory.
   std::error_code EC;
-  llvm::sys::fs::file_status Status;
   for (llvm::sys::fs::directory_iterator I(Directory.str(), EC), E; I != E;
     I.increment(EC)) {
     if (EC)
       return false;
     std::string File(I->path());
-    I->status(Status);
-    llvm::sys::fs::file_type Type = Status.type();
+    llvm::ErrorOr<llvm::sys::fs::basic_file_status> Status = I->status();
+    if (!Status)
+      return false;
+    llvm::sys::fs::file_type Type = Status->type();
     // If the file is a directory, ignore the name and recurse.
     if (Type == llvm::sys::fs::file_type::directory_file) {
       if (!collectUmbrellaHeaders(File, Dependents))
diff --git a/modularize/ModuleAssistant.cpp b/modularize/ModuleAssistant.cpp
index 26c5925..7f1cb15 100644
--- a/modularize/ModuleAssistant.cpp
+++ b/modularize/ModuleAssistant.cpp
@@ -25,7 +25,7 @@
 // to modularize.  It then calls a writeModuleMap function to set up the
 // module map file output and walk the module tree, outputting the module
 // map file using a stream obtained and managed by an
-// llvm::tool_output_file object.
+// llvm::ToolOutputFile object.
 //
 //===---------------------------------------------------------------------===//
 
@@ -271,7 +271,7 @@
 
   // Set up module map output file.
   std::error_code EC;
-  llvm::tool_output_file Out(FilePath, EC, llvm::sys::fs::F_Text);
+  llvm::ToolOutputFile Out(FilePath, EC, llvm::sys::fs::F_Text);
   if (EC) {
     llvm::errs() << Argv0 << ": error opening " << FilePath << ":"
                  << EC.message() << "\n";
@@ -289,7 +289,7 @@
   if (!RootModule->output(OS, 0))
     return false;
 
-  // Tell tool_output_file that we want to keep the file.
+  // Tell ToolOutputFile that we want to keep the file.
   Out.keep();
 
   return true;
diff --git a/modularize/PreprocessorTracker.cpp b/modularize/PreprocessorTracker.cpp
index 3193568..a9d61f0 100644
--- a/modularize/PreprocessorTracker.cpp
+++ b/modularize/PreprocessorTracker.cpp
@@ -407,7 +407,7 @@
   // Walk over the macro Tokens.
   for (const auto &T : MI->tokens()) {
     clang::IdentifierInfo *II = T.getIdentifierInfo();
-    int ArgNo = (II && Args ? MI->getArgumentNum(II) : -1);
+    int ArgNo = (II && Args ? MI->getParameterNum(II) : -1);
     if (ArgNo == -1) {
       // This isn't an argument, just add it.
       if (II == nullptr)
@@ -429,7 +429,7 @@
     const clang::Token *ArgTok = Args->getUnexpArgument(ArgNo);
     if (Args->ArgNeedsPreexpansion(ArgTok, PP))
       ResultArgToks = &(const_cast<clang::MacroArgs *>(Args))
-          ->getPreExpArgument(ArgNo, MI, PP)[0];
+          ->getPreExpArgument(ArgNo, PP)[0];
     else
       ResultArgToks = ArgTok; // Use non-preexpanded Tokens.
     // If the arg token didn't expand into anything, ignore it.
diff --git a/pp-trace/PPCallbacksTracker.cpp b/pp-trace/PPCallbacksTracker.cpp
index ca634d2..4bb126c 100644
--- a/pp-trace/PPCallbacksTracker.cpp
+++ b/pp-trace/PPCallbacksTracker.cpp
@@ -342,9 +342,10 @@
 }
 
 // Hook called when a source range is skipped.
-void PPCallbacksTracker::SourceRangeSkipped(clang::SourceRange Range) {
+void PPCallbacksTracker::SourceRangeSkipped(clang::SourceRange Range,
+                                            clang::SourceLocation EndifLoc) {
   beginCallback("SourceRangeSkipped");
-  appendArgument("Range", Range);
+  appendArgument("Range", clang::SourceRange(Range.getBegin(), EndifLoc));
 }
 
 // Hook called whenever an #if is seen.
diff --git a/pp-trace/PPCallbacksTracker.h b/pp-trace/PPCallbacksTracker.h
index 65c7fa1..7b57d34 100644
--- a/pp-trace/PPCallbacksTracker.h
+++ b/pp-trace/PPCallbacksTracker.h
@@ -145,7 +145,8 @@
   void Defined(const clang::Token &MacroNameTok,
                const clang::MacroDefinition &MD,
                clang::SourceRange Range) override;
-  void SourceRangeSkipped(clang::SourceRange Range) override;
+  void SourceRangeSkipped(clang::SourceRange Range,
+                          clang::SourceLocation EndifLoc) override;
   void If(clang::SourceLocation Loc, clang::SourceRange ConditionRange,
           ConditionValueKind ConditionValue) override;
   void Elif(clang::SourceLocation Loc, clang::SourceRange ConditionRange,
diff --git a/pp-trace/PPTrace.cpp b/pp-trace/PPTrace.cpp
index 0a50792..d49bc20 100644
--- a/pp-trace/PPTrace.cpp
+++ b/pp-trace/PPTrace.cpp
@@ -215,7 +215,7 @@
   } else {
     // Set up output file.
     std::error_code EC;
-    llvm::tool_output_file Out(OutputFileName, EC, llvm::sys::fs::F_Text);
+    llvm::ToolOutputFile Out(OutputFileName, EC, llvm::sys::fs::F_Text);
     if (EC) {
       llvm::errs() << "pp-trace: error creating " << OutputFileName << ":"
                    << EC.message() << "\n";
@@ -224,7 +224,7 @@
 
     HadErrors = outputPPTrace(CallbackCalls, Out.os());
 
-    // Tell tool_output_file that we want to keep the file.
+    // Tell ToolOutputFile that we want to keep the file.
     if (HadErrors == 0)
       Out.keep();
   }
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index be652e3..90de6c7 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -15,6 +15,9 @@
 
 string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} CLANG_TOOLS_DIR ${LLVM_RUNTIME_OUTPUT_INTDIR})
 
+llvm_canonicalize_cmake_booleans(
+  CLANG_ENABLE_STATIC_ANALYZER)
+
 configure_lit_site_cfg(
   ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
   ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
@@ -31,11 +34,8 @@
 endif()
 
 set(CLANG_TOOLS_TEST_DEPS
-  # clang-tidy tests require it.
-  clang-headers
-
-  # For the clang-tidy libclang integration test.
-  c-index-test
+  # For the clang-apply-replacements test that uses clang-rename.
+  clang-rename
 
   # Individual tools we test.
   clang-apply-replacements
@@ -44,9 +44,7 @@
   clang-include-fixer
   clang-move
   clang-query
-  clang-rename
   clang-reorder-fields
-  clang-tidy
   find-all-symbols
   modularize
   pp-trace
@@ -55,6 +53,17 @@
   ExtraToolsUnitTests
   )
 
+if(CLANG_ENABLE_STATIC_ANALYZER)
+  list(APPEND CLANG_TOOLS_TEST_DEPS
+    # For the clang-tidy libclang integration test.
+    c-index-test
+    # clang-tidy tests require it.
+    clang-headers
+
+    clang-tidy
+    )
+endif()
+
 set(llvm_utils
   FileCheck count not
   )
@@ -70,5 +79,5 @@
   DEPENDS ${CLANG_TOOLS_TEST_DEPS}
   ARGS ${CLANG_TOOLS_TEST_EXTRA_ARGS}
   )
-set_target_properties(check-clang-tools PROPERTIES FOLDER "Clang extra tools' tests")
 
+set_target_properties(check-clang-tools PROPERTIES FOLDER "Clang extra tools' tests")
diff --git a/test/Unit/lit.cfg b/test/Unit/lit.cfg
index ff70123..fc63afd 100644
--- a/test/Unit/lit.cfg
+++ b/test/Unit/lit.cfg
@@ -9,10 +9,9 @@
 
 # Test Source and Exec root dirs both point to the same directory where google
 # test binaries are built.
-extra_tools_obj_dir = getattr(config, 'extra_tools_obj_dir', None)
-if extra_tools_obj_dir is not None:
-  config.test_source_root = extra_tools_obj_dir
-  config.test_exec_root = config.test_source_root
+
+config.test_source_root = config.extra_tools_obj_dir
+config.test_exec_root = config.test_source_root
 
 # All GoogleTests are named to have 'Tests' as their suffix. The '.' option is
 # a special value for GoogleTest indicating that it should look through the
@@ -20,18 +19,6 @@
 # ;-separated list of subdirectories).
 config.test_format = lit.formats.GoogleTest('.', 'Tests')
 
-# If the site-specific configuration wasn't loaded (e.g. the build system failed
-# to create it or the user is running a test file directly) try to come up with
-# sane config options.
-if config.test_exec_root is None:
-  # Look for a --param=extra_tools_unit_site_config option.
-  site_cfg = lit_config.params.get('extra_tools_unit_site_config', None)
-  if site_cfg and os.path.exists(site_cfg):
-      lit_config.load_config(config, site_cfg)
-      raise SystemExit
-
-  # FIXME: Support out-of-tree builds? See clang/test/Unit/lit.cfg if we care.
-
 shlibpath_var = ''
 if platform.system() == 'Linux':
     shlibpath_var = 'LD_LIBRARY_PATH'
@@ -41,10 +28,7 @@
     shlibpath_var = 'PATH'
 
 # Point the dynamic loader at dynamic libraries in 'lib'.
-llvm_libs_dir = getattr(config, 'llvm_libs_dir', None)
-if not llvm_libs_dir:
-    lit_config.fatal('No LLVM libs dir set!')
-shlibpath = os.path.pathsep.join((llvm_libs_dir,
+shlibpath = os.path.pathsep.join((config.shlibdir, config.llvm_libs_dir,
                                  config.environment.get(shlibpath_var,'')))
 
 # Win32 seeks DLLs along %PATH%.
diff --git a/test/clang-rename/ClassReplacements.cpp b/test/clang-apply-replacements/ClangRenameClassReplacements.cpp
similarity index 100%
rename from test/clang-rename/ClassReplacements.cpp
rename to test/clang-apply-replacements/ClangRenameClassReplacements.cpp
diff --git a/test/clang-apply-replacements/Inputs/basic/file1.yaml b/test/clang-apply-replacements/Inputs/basic/file1.yaml
index 7f41727..3a5375e 100644
--- a/test/clang-apply-replacements/Inputs/basic/file1.yaml
+++ b/test/clang-apply-replacements/Inputs/basic/file1.yaml
@@ -2,6 +2,9 @@
 MainSourceFile:     source1.cpp
 Diagnostics:
   - DiagnosticName: test-basic
+    Message: Fix
+    FilePath: $(path)/basic.h
+    FileOffset: 242
     Replacements:
       - FilePath:        $(path)/basic.h
         Offset:          242
diff --git a/test/clang-apply-replacements/Inputs/basic/file2.yaml b/test/clang-apply-replacements/Inputs/basic/file2.yaml
index 1edb783..52d2fe8 100644
--- a/test/clang-apply-replacements/Inputs/basic/file2.yaml
+++ b/test/clang-apply-replacements/Inputs/basic/file2.yaml
@@ -2,6 +2,9 @@
 MainSourceFile:     source2.cpp
 Diagnostics:
   - DiagnosticName: test-basic
+    Message: Fix
+    FilePath: $(path)/basic.h
+    FileOffset: 148
     Replacements:
       - FilePath:        $(path)/basic.h
         Offset:          148
diff --git a/test/clang-apply-replacements/Inputs/conflict/file1.yaml b/test/clang-apply-replacements/Inputs/conflict/file1.yaml
index c8ae3a0..8505273 100644
--- a/test/clang-apply-replacements/Inputs/conflict/file1.yaml
+++ b/test/clang-apply-replacements/Inputs/conflict/file1.yaml
@@ -2,6 +2,9 @@
 MainSourceFile: source1.cpp
 Diagnostics:
   - DiagnosticName: test-conflict
+    Message: Fix
+    FilePath: $(path)/common.h
+    FileOffset: 106
     Replacements:
       - FilePath:        $(path)/common.h
         Offset:          106
diff --git a/test/clang-apply-replacements/Inputs/conflict/file2.yaml b/test/clang-apply-replacements/Inputs/conflict/file2.yaml
index dbd874d..32b35ac 100644
--- a/test/clang-apply-replacements/Inputs/conflict/file2.yaml
+++ b/test/clang-apply-replacements/Inputs/conflict/file2.yaml
@@ -1,7 +1,10 @@
 ---
 MainSourceFile: source2.cpp
-Diagnostics:     
+Diagnostics:
   - DiagnosticName:  test-conflict
+    Message: Fix
+    FilePath: $(path)/common.h
+    FileOffset: 106
     Replacements:
       - FilePath:        $(path)/common.h
         Offset:          106
diff --git a/test/clang-apply-replacements/Inputs/conflict/file3.yaml b/test/clang-apply-replacements/Inputs/conflict/file3.yaml
index 7227a07..88543e0 100644
--- a/test/clang-apply-replacements/Inputs/conflict/file3.yaml
+++ b/test/clang-apply-replacements/Inputs/conflict/file3.yaml
@@ -2,6 +2,9 @@
 MainSourceFile: source1.cpp
 Diagnostics:
   - DiagnosticName:  test-conflict
+    Message: Fix
+    FilePath: $(path)/common.h
+    FileOffset: 169
     Replacements:
       - FilePath:        $(path)/common.h
         Offset:          169
diff --git a/test/clang-apply-replacements/Inputs/crlf/file1.yaml b/test/clang-apply-replacements/Inputs/crlf/file1.yaml
index 1f6b89c..06b058e 100644
--- a/test/clang-apply-replacements/Inputs/crlf/file1.yaml
+++ b/test/clang-apply-replacements/Inputs/crlf/file1.yaml
@@ -2,7 +2,10 @@
 MainSourceFile:      source1.cpp
 Diagnostics:
   - DiagnosticName:  test-crlf
-    Replacements:    
+    Message: Fix
+    FilePath: $(path)/crlf.cpp
+    FileOffset: 79
+    Replacements:
       - FilePath:        $(path)/crlf.cpp
         Offset:          79
         Length:          1
diff --git a/test/clang-apply-replacements/Inputs/format/no.yaml b/test/clang-apply-replacements/Inputs/format/no.yaml
index ea7a3f7..3118cc6 100644
--- a/test/clang-apply-replacements/Inputs/format/no.yaml
+++ b/test/clang-apply-replacements/Inputs/format/no.yaml
@@ -1,8 +1,11 @@
 ---
 MainSourceFile:  no.cpp
-Diagnostics:     
+Diagnostics:
   - DiagnosticName:  test-no
-    Replacements:    
+    Message: Fix
+    FilePath: $(path)/no.cpp
+    FileOffset: 94
+    Replacements:
       - FilePath:        $(path)/no.cpp
         Offset:          94
         Length:          3
diff --git a/test/clang-apply-replacements/Inputs/format/yes.yaml b/test/clang-apply-replacements/Inputs/format/yes.yaml
index df5022e..6ded4db 100644
--- a/test/clang-apply-replacements/Inputs/format/yes.yaml
+++ b/test/clang-apply-replacements/Inputs/format/yes.yaml
@@ -2,9 +2,12 @@
 # so that formatting happens correctly.
 ---
 MainSourceFile:  yes.cpp
-Diagnostics:     
+Diagnostics:
   - DiagnosticName:  test-yes
-    Replacements:    
+    Message: Fix
+    FilePath: $(path)/yes.cpp
+    FileOffset: 494
+    Replacements:
       - FilePath:        $(path)/yes.cpp
         Offset:          494
         Length:          1
diff --git a/test/clang-apply-replacements/Inputs/invalid-files/invalid-files.yaml b/test/clang-apply-replacements/Inputs/invalid-files/invalid-files.yaml
new file mode 100644
index 0000000..f84964d
--- /dev/null
+++ b/test/clang-apply-replacements/Inputs/invalid-files/invalid-files.yaml
@@ -0,0 +1,12 @@
+---
+MainSourceFile:  ''
+Replacements:
+  - FilePath:        idontexist.h
+    Offset:          2669
+    Length:          0
+    ReplacementText: ' override'
+  - FilePath:        idontexist.h
+    Offset:          2669
+    Length:          0
+    ReplacementText: ' override'
+...
diff --git a/test/clang-apply-replacements/invalid-files.cpp b/test/clang-apply-replacements/invalid-files.cpp
new file mode 100644
index 0000000..b0eb9ef
--- /dev/null
+++ b/test/clang-apply-replacements/invalid-files.cpp
@@ -0,0 +1,6 @@
+// RUN: mkdir -p %T/invalid-files
+// RUN: cp %S/Inputs/invalid-files/invalid-files.yaml %T/invalid-files/invalid-files.yaml
+// RUN: clang-apply-replacements %T/invalid-files
+//
+// Check that the yaml files are *not* deleted after running clang-apply-replacements without remove-change-desc-files.
+// RUN: ls %T/invalid-files/invalid-files.yaml
diff --git a/test/clang-rename/ClassAsTemplateArgument.cpp b/test/clang-rename/ClassAsTemplateArgument.cpp
deleted file mode 100644
index 2e09a5b..0000000
--- a/test/clang-rename/ClassAsTemplateArgument.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-class Foo /* Test 1 */ {};    // CHECK: class Bar /* Test 1 */ {};
-
-template <typename T>
-void func() {}
-
-template <typename T>
-class Baz {};
-
-int main() {
-  func<Foo>();                // CHECK: func<Bar>();
-  Baz<Foo> /* Test 2 */ obj;  // CHECK: Baz<Bar> /* Test 2 */ obj;
-  return 0;
-}
-
-// Test 1.
-// RUN: clang-rename -offset=7 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
-// Test 2.
-// RUN: clang-rename -offset=215 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
-
-// To find offsets after modifying the file, use:
-//   grep -Ubo 'Foo.*' <file>
diff --git a/test/clang-rename/ClassFindByName.cpp b/test/clang-rename/ClassFindByName.cpp
deleted file mode 100644
index 4430891..0000000
--- a/test/clang-rename/ClassFindByName.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-class Foo {         // CHECK: class Bar {
-};
-
-int main() {
-  Foo *Pointer = 0; // CHECK: Bar *Pointer = 0;
-  return 0;
-}
-
-// Test 1.
-// RUN: clang-rename -qualified-name=Foo -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
diff --git a/test/clang-rename/ClassSimpleRenaming.cpp b/test/clang-rename/ClassSimpleRenaming.cpp
deleted file mode 100644
index 086f557..0000000
--- a/test/clang-rename/ClassSimpleRenaming.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-class Foo /* Test 1 */ {              // CHECK: class Bar /* Test 1 */ {
-public:
-  void foo(int x);
-};
-
-void Foo::foo(int x) /* Test 2 */ {}  // CHECK: void Bar::foo(int x) /* Test 2 */ {}
-
-// Test 1.
-// RUN: clang-rename -offset=6 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
-// Test 2.
-// RUN: clang-rename -offset=109 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
-
-// To find offsets after modifying the file, use:
-//   grep -Ubo 'Foo.*' <file>
diff --git a/test/clang-rename/ClassTestMulti.cpp b/test/clang-rename/ClassTestMulti.cpp
deleted file mode 100644
index 81e65c7..0000000
--- a/test/clang-rename/ClassTestMulti.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-class Foo1 /* Offset 1 */ { // CHECK: class Bar1 /* Offset 1 */ {
-};
-
-class Foo2 /* Offset 2 */ { // CHECK: class Bar2 /* Offset 2 */ {
-};
-
-// Test 1.
-// RUN: clang-rename -offset=6 -new-name=Bar1 -offset=76 -new-name=Bar2 %s -- | sed 's,//.*,,' | FileCheck %s
-
-// To find offsets after modifying the file, use:
-//   grep -Ubo 'Foo.*' <file>
diff --git a/test/clang-rename/ClassTestMultiByName.cpp b/test/clang-rename/ClassTestMultiByName.cpp
deleted file mode 100644
index 61b69a1..0000000
--- a/test/clang-rename/ClassTestMultiByName.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-class Foo1 { // CHECK: class Bar1
-};
-
-class Foo2 { // CHECK: class Bar2
-};
-
-// Test 1.
-// RUN: clang-rename -qualified-name=Foo1 -new-name=Bar1 -qualified-name=Foo2 -new-name=Bar2 %s -- | sed 's,//.*,,' | FileCheck %s
diff --git a/test/clang-rename/ComplexFunctionOverride.cpp b/test/clang-rename/ComplexFunctionOverride.cpp
deleted file mode 100644
index ccf3a20..0000000
--- a/test/clang-rename/ComplexFunctionOverride.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-struct A {
-  virtual void foo() {} /* Test 1 */    // CHECK: virtual void bar() {}
-};
-
-struct B : A {
-  void foo() override {} /* Test 2 */   // CHECK: void bar() override {}
-};
-
-struct C : B {
-  void foo() override {} /* Test 3 */   // CHECK: void bar() override {}
-};
-
-struct D : B {
-  void foo() override {} /* Test 4 */   // CHECK: void bar() override {}
-};
-
-struct E : D {
-  void foo() override {} /* Test 5 */   // CHECK: void bar() override {}
-};
-
-int main() {
-  A a;
-  a.foo();                              // CHECK: a.bar();
-  B b;
-  b.foo();                              // CHECK: b.bar();
-  C c;
-  c.foo();                              // CHECK: c.bar();
-  D d;
-  d.foo();                              // CHECK: d.bar();
-  E e;
-  e.foo();                              // CHECK: e.bar();
-  return 0;
-}
-
-// Test 1.
-// RUN: clang-rename -offset=26 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s
-// Test 2.
-// RUN: clang-rename -offset=109 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s
-// Test 3.
-// RUN: clang-rename -offset=201 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s
-// Test 4.
-// RUN: clang-rename -offset=293 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s
-// Test 5.
-// RUN: clang-rename -offset=385 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s
-
-// To find offsets after modifying the file, use:
-//   grep -Ubo 'foo.*' <file>
diff --git a/test/clang-rename/ComplicatedClassType.cpp b/test/clang-rename/ComplicatedClassType.cpp
deleted file mode 100644
index 8801953..0000000
--- a/test/clang-rename/ComplicatedClassType.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-// Forward declaration.
-class Foo; /* Test 1 */               // CHECK: class Bar; /* Test 1 */
-
-class Baz {
-  virtual int getValue() const = 0;
-};
-
-class Foo : public Baz  { /* Test 2 */// CHECK: class Bar : public Baz {
-public:
-  Foo(int value = 0) : x(value) {}    // CHECK: Bar(int value = 0) : x(value) {}
-
-  Foo &operator++(int) {              // CHECK: Bar &operator++(int) {
-    x++;
-    return *this;
-  }
-
-  bool operator<(Foo const &rhs) {    // CHECK: bool operator<(Bar const &rhs) {
-    return this->x < rhs.x;
-  }
-
-  int getValue() const {
-    return 0;
-  }
-
-private:
-  int x;
-};
-
-int main() {
-  Foo *Pointer = 0;                   // CHECK: Bar *Pointer = 0;
-  Foo Variable = Foo(10);             // CHECK: Bar Variable = Bar(10);
-  for (Foo it; it < Variable; it++) { // CHECK: for (Bar it; it < Variable; it++) {
-  }
-  const Foo *C = new Foo();           // CHECK: const Bar *C = new Bar();
-  const_cast<Foo *>(C)->getValue();   // CHECK: const_cast<Bar *>(C)->getValue();
-  Foo foo;                            // CHECK: Bar foo;
-  const Baz &BazReference = foo;
-  const Baz *BazPointer = &foo;
-  dynamic_cast<const Foo &>(BazReference).getValue();     /* Test 3 */ // CHECK: dynamic_cast<const Bar &>(BazReference).getValue();
-  dynamic_cast<const Foo *>(BazPointer)->getValue();      /* Test 4 */ // CHECK: dynamic_cast<const Bar *>(BazPointer)->getValue();
-  reinterpret_cast<const Foo *>(BazPointer)->getValue();  /* Test 5 */ // CHECK: reinterpret_cast<const Bar *>(BazPointer)->getValue();
-  static_cast<const Foo &>(BazReference).getValue();      /* Test 6 */ // CHECK: static_cast<const Bar &>(BazReference).getValue();
-  static_cast<const Foo *>(BazPointer)->getValue();       /* Test 7 */ // CHECK: static_cast<const Bar *>(BazPointer)->getValue();
-  return 0;
-}
-
-// Test 1.
-// RUN: clang-rename -offset=30 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s
-// Test 2.
-// RUN: clang-rename -offset=155 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s
-// Test 3.
-// RUN: clang-rename -offset=1133 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s
-// Test 4.
-// RUN: clang-rename -offset=1266 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s
-// Test 5.
-// RUN: clang-rename -offset=1402 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s
-// Test 6.
-// RUN: clang-rename -offset=1533 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s
-// Test 7.
-// RUN: clang-rename -offset=1665 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s
-
-// To find offsets after modifying the file, use:
-//   grep -Ubo 'Foo.*' <file>
diff --git a/test/clang-rename/Ctor.cpp b/test/clang-rename/Ctor.cpp
deleted file mode 100644
index 9908a41..0000000
--- a/test/clang-rename/Ctor.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-class Foo {                   // CHECK: class Bar {
-public:
-  Foo();    /* Test 1 */      // CHECK: Bar();
-};
-
-Foo::Foo()  /* Test 2 */ {}   // CHECK: Bar::Bar()  /* Test 2 */ {}
-
-// Test 1.
-// RUN: clang-rename -offset=62 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
-// Test 2.
-// RUN: clang-rename -offset=116 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
-
-// To find offsets after modifying the file, use:
-//   grep -Ubo 'Foo.*' <file>
diff --git a/test/clang-rename/CtorInitializer.cpp b/test/clang-rename/CtorInitializer.cpp
deleted file mode 100644
index fed4f5b..0000000
--- a/test/clang-rename/CtorInitializer.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-class Baz {};
-
-class Qux {
-  Baz Foo;         /* Test 1 */       // CHECK: Baz Bar;
-public:
-  Qux();
-};
-
-Qux::Qux() : Foo() /* Test 2 */ {}    // CHECK: Qux::Qux() : Bar() /* Test 2 */ {}
-
-// Test 1.
-// RUN: clang-rename -offset=33 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
-// Test 2.
-// RUN: clang-rename -offset=118 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
-
-// To find offsets after modifying the file, use:
-//   grep -Ubo 'Foo.*' <file>
diff --git a/test/clang-rename/DeclRefExpr.cpp b/test/clang-rename/DeclRefExpr.cpp
deleted file mode 100644
index 6462862..0000000
--- a/test/clang-rename/DeclRefExpr.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-class C {
-public:
-  static int Foo; /* Test 1 */  // CHECK: static int Bar;
-};
-
-int foo(int x) { return 0; }
-#define MACRO(a) foo(a)
-
-int main() {
-  C::Foo = 1;     /* Test 2 */  // CHECK: C::Bar = 1;
-  MACRO(C::Foo);                // CHECK: MACRO(C::Bar);
-  int y = C::Foo; /* Test 3 */  // CHECK: int y = C::Bar;
-  return 0;
-}
-
-// Test 1.
-// RUN: clang-rename -offset=31 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
-// Test 2.
-// RUN: clang-rename -offset=152 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
-// Test 3.
-// RUN: clang-rename -offset=271 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
-
-// To find offsets after modifying the file, use:
-//   grep -Ubo 'Foo.*' <file>
diff --git a/test/clang-rename/Field.cpp b/test/clang-rename/Field.cpp
deleted file mode 100644
index c0e9a01..0000000
--- a/test/clang-rename/Field.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-class Baz {
-  int Foo; /* Test 1 */ // CHECK: int Bar;
-public:
-  Baz();
-};
-
-Baz::Baz() : Foo(0) /* Test 2 */ {}  // CHECK: Baz::Baz() : Bar(0)
-
-// Test 1.
-// RUN: clang-rename -offset=18 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
-// Test 2.
-// RUN: clang-rename -offset=89 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
-
-// To find offsets after modifying the file, use:
-//   grep -Ubo 'Foo.*' <file>
diff --git a/test/clang-rename/FunctionMacro.cpp b/test/clang-rename/FunctionMacro.cpp
deleted file mode 100644
index 6e87026..0000000
--- a/test/clang-rename/FunctionMacro.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#define moo foo           // CHECK: #define moo macro_function
-
-int foo() /* Test 1 */ {  // CHECK: int macro_function() /* Test 1 */ {
-  return 42;
-}
-
-void boo(int value) {}
-
-void qoo() {
-  foo();                  // CHECK: macro_function();
-  boo(foo());             // CHECK: boo(macro_function());
-  moo();
-  boo(moo());
-}
-
-// Test 1.
-// RUN: clang-rename -offset=68 -new-name=macro_function %s -- | sed 's,//.*,,' | FileCheck %s
-
-// To find offsets after modifying the file, use:
-//   grep -Ubo 'foo.*' <file>
diff --git a/test/clang-rename/FunctionOverride.cpp b/test/clang-rename/FunctionOverride.cpp
deleted file mode 100644
index adfeb73..0000000
--- a/test/clang-rename/FunctionOverride.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-class A { virtual void foo();     /* Test 1 */ }; // CHECK: class A { virtual void bar();
-class B : public A { void foo();  /* Test 2 */ }; // CHECK: class B : public A { void bar();
-class C : public B { void foo();  /* Test 3 */ }; // CHECK: class C : public B { void bar();
-
-// Test 1.
-// RUN: clang-rename -offset=23 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s
-// Test 2.
-// RUN: clang-rename -offset=116 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s
-// Test 3.
-// RUN: clang-rename -offset=209 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s
-
-// To find offsets after modifying the file, use:
-//   grep -Ubo 'foo.*' <file>
diff --git a/test/clang-rename/FunctionWithClassFindByName.cpp b/test/clang-rename/FunctionWithClassFindByName.cpp
deleted file mode 100644
index 2cae09a..0000000
--- a/test/clang-rename/FunctionWithClassFindByName.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-void foo() {
-}
-
-class Foo {         // CHECK: class Bar
-};
-
-int main() {
-  Foo *Pointer = 0; // CHECK: Bar *Pointer = 0;
-  return 0;
-}
-
-// RUN: clang-rename -qualified-name=Foo -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
diff --git a/test/clang-rename/IncludeHeaderWithSymbol.cpp b/test/clang-rename/IncludeHeaderWithSymbol.cpp
deleted file mode 100644
index cb2baee..0000000
--- a/test/clang-rename/IncludeHeaderWithSymbol.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-#include "Inputs/HeaderWithSymbol.h"
-
-int main() {
-  return 0; // CHECK: {{^  return 0;}}
-}
-
-// Test 1.
-// The file IncludeHeaderWithSymbol.cpp doesn't contain the symbol Foo
-// and is expected to be written to stdout without modifications
-// RUN: clang-rename -qualified-name=Foo -new-name=Bar %s -- | FileCheck %s
diff --git a/test/clang-rename/Inputs/HeaderWithSymbol.h b/test/clang-rename/Inputs/HeaderWithSymbol.h
deleted file mode 100644
index 1fe02e8..0000000
--- a/test/clang-rename/Inputs/HeaderWithSymbol.h
+++ /dev/null
@@ -1 +0,0 @@
-struct Foo {};
diff --git a/test/clang-rename/Inputs/OffsetToNewName.yaml b/test/clang-rename/Inputs/OffsetToNewName.yaml
deleted file mode 100644
index d8e9728..0000000
--- a/test/clang-rename/Inputs/OffsetToNewName.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-- Offset:         6
-  NewName:        Bar1
-- Offset:         44
-  NewName:        Bar2
-...
diff --git a/test/clang-rename/Inputs/QualifiedNameToNewName.yaml b/test/clang-rename/Inputs/QualifiedNameToNewName.yaml
deleted file mode 100644
index 6e37836..0000000
--- a/test/clang-rename/Inputs/QualifiedNameToNewName.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-- QualifiedName:  Foo1
-  NewName:        Bar1
-- QualifiedName:  Foo2
-  NewName:        Bar2
-...
diff --git a/test/clang-rename/InvalidNewName.cpp b/test/clang-rename/InvalidNewName.cpp
deleted file mode 100644
index e6b38e5..0000000
--- a/test/clang-rename/InvalidNewName.cpp
+++ /dev/null
@@ -1,2 +0,0 @@
-// RUN: not clang-rename -new-name=class -offset=133 %s 2>&1 | FileCheck %s
-// CHECK: ERROR: new name is not a valid identifier in C++17.
diff --git a/test/clang-rename/InvalidOffset.cpp b/test/clang-rename/InvalidOffset.cpp
deleted file mode 100644
index 2ae04d0..0000000
--- a/test/clang-rename/InvalidOffset.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-#include "Inputs/HeaderWithSymbol.h"
-#define FOO int bar;
-FOO
-
-int foo;
-
-// RUN: not clang-rename -new-name=qux -offset=259 %s -- 2>&1 | FileCheck %s
-// CHECK-NOT: CHECK
-// CHECK: error: SourceLocation in file {{.*}}InvalidOffset.cpp at offset 259 is invalid
diff --git a/test/clang-rename/InvalidQualifiedName.cpp b/test/clang-rename/InvalidQualifiedName.cpp
deleted file mode 100644
index 5280e39..0000000
--- a/test/clang-rename/InvalidQualifiedName.cpp
+++ /dev/null
@@ -1,4 +0,0 @@
-struct S {
-};
-
-// RUN: clang-rename -force -qualified-name S2 -new-name=T %s --
diff --git a/test/clang-rename/MemberExprMacro.cpp b/test/clang-rename/MemberExprMacro.cpp
deleted file mode 100644
index 56cd8d9..0000000
--- a/test/clang-rename/MemberExprMacro.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-class Baz {
-public:
-  int Foo;  /* Test 1 */    // CHECK: int Bar;
-};
-
-int qux(int x) { return 0; }
-#define MACRO(a) qux(a)
-
-int main() {
-  Baz baz;
-  baz.Foo = 1; /* Test 2 */ // CHECK: baz.Bar = 1;
-  MACRO(baz.Foo);           // CHECK: MACRO(baz.Bar);
-  int y = baz.Foo;          // CHECK: int y = baz.Bar;
-}
-
-// Test 1.
-// RUN: clang-rename -offset=26 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
-// Test 2.
-// RUN: clang-rename -offset=155 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
-
-// To find offsets after modifying the file, use:
-//   grep -Ubo 'Foo.*' <file>
diff --git a/test/clang-rename/Namespace.cpp b/test/clang-rename/Namespace.cpp
deleted file mode 100644
index ec9630f..0000000
--- a/test/clang-rename/Namespace.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-namespace gcc /* Test 1 */ {  // CHECK: namespace clang /* Test 1 */ {
-  int x;
-}
-
-void boo() {
-  gcc::x = 42;                // CHECK: clang::x = 42;
-}
-
-// Test 1.
-// RUN: clang-rename -offset=10 -new-name=clang %s -- | sed 's,//.*,,' | FileCheck %s
-
-// To find offsets after modifying the file, use:
-//   grep -Ubo 'Foo.*' <file>
diff --git a/test/clang-rename/NoNewName.cpp b/test/clang-rename/NoNewName.cpp
deleted file mode 100644
index 4f882d8..0000000
--- a/test/clang-rename/NoNewName.cpp
+++ /dev/null
@@ -1,4 +0,0 @@
-// Check for an error while -new-name argument has not been passed to
-// clang-rename.
-// RUN: not clang-rename -offset=133 %s 2>&1 | FileCheck %s
-// CHECK: clang-rename: -new-name must be specified.
diff --git a/test/clang-rename/TemplateClassInstantiation.cpp b/test/clang-rename/TemplateClassInstantiation.cpp
deleted file mode 100644
index 493d095..0000000
--- a/test/clang-rename/TemplateClassInstantiation.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-template <typename T>
-class Foo { /* Test 1 */   // CHECK: class Bar { /* Test 1 */
-public:
-  T foo(T arg, T& ref, T* ptr) {
-    T value;
-    int number = 42;
-    value = (T)number;
-    value = static_cast<T>(number);
-    return value;
-  }
-  static void foo(T value) {}
-  T member;
-};
-
-template <typename T>
-void func() {
-  Foo<T> obj; /* Test 2 */  // CHECK: Bar<T> obj;
-  obj.member = T();
-  Foo<T>::foo();            // CHECK: Bar<T>::foo();
-}
-
-int main() {
-  Foo<int> i; /* Test 3 */  // CHECK: Bar<int> i;
-  i.member = 0;
-  Foo<int>::foo(0);         // CHECK: Bar<int>::foo(0);
-
-  Foo<bool> b;              // CHECK: Bar<bool> b;
-  b.member = false;
-  Foo<bool>::foo(false);    // CHECK: Bar<bool>::foo(false);
-
-  return 0;
-}
-
-// Test 1.
-// RUN: clang-rename -offset=29 -new-name=Bar %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s
-// Test 2.
-// RUN: clang-rename -offset=324 -new-name=Bar %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s
-// Test 3.
-// RUN: clang-rename -offset=463 -new-name=Bar %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s
-
-// To find offsets after modifying the file, use:
-//   grep -Ubo 'Foo.*' <file>
diff --git a/test/clang-rename/TemplateTypename.cpp b/test/clang-rename/TemplateTypename.cpp
deleted file mode 100644
index 559ec1f..0000000
--- a/test/clang-rename/TemplateTypename.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-template <typename T /* Test 1 */>              // CHECK: template <typename U /* Test 1 */>
-class Foo {
-T foo(T arg, T& ref, T* /* Test 2 */ ptr) {     // CHECK: U foo(U arg, U& ref, U* /* Test 2 */ ptr) {
-  T value;                                      // CHECK: U value;
-  int number = 42;
-  value = (T)number;                            // CHECK: value = (U)number;
-  value = static_cast<T /* Test 3 */>(number);  // CHECK: value = static_cast<U /* Test 3 */>(number);
-  return value;
-}
-
-static void foo(T value) {}                     // CHECK: static void foo(U value) {}
-
-T member;                                       // CHECK: U member;
-};
-
-// Test 1.
-// RUN: clang-rename -offset=19 -new-name=U %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s
-// Test 2.
-// RUN: clang-rename -offset=126 -new-name=U %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s
-// Test 3.
-// RUN: clang-rename -offset=392 -new-name=U %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s
-
-// To find offsets after modifying the file, use:
-//   grep -Ubo 'T.*' <file>
diff --git a/test/clang-rename/TemplatedClassFunction.cpp b/test/clang-rename/TemplatedClassFunction.cpp
deleted file mode 100644
index 1f5b0b5..0000000
--- a/test/clang-rename/TemplatedClassFunction.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-template <typename T>
-class A {
-public:
-  void foo() /* Test 1 */ {}  // CHECK: void bar() /* Test 1 */ {}
-};
-
-int main(int argc, char **argv) {
-  A<int> a;
-  a.foo();   /* Test 2 */     // CHECK: a.bar()   /* Test 2 */
-  return 0;
-}
-
-// Test 1.
-// RUN: clang-refactor rename -offset=48 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s
-// Test 2.
-// RUN: clang-refactor rename -offset=162 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s
-//
-// Currently unsupported test.
-// XFAIL: *
-
-// To find offsets after modifying the file, use:
-//   grep -Ubo 'foo.*' <file>
diff --git a/test/clang-rename/UserDefinedConversion.cpp b/test/clang-rename/UserDefinedConversion.cpp
deleted file mode 100644
index 60f251a..0000000
--- a/test/clang-rename/UserDefinedConversion.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-class Foo {       /* Test 1 */          // CHECK: class Bar {
-public:
-  Foo() {}                              // CHECK: Bar() {}
-};
-
-class Baz {
-public:
-  operator Foo()  /* Test 2 */ const {  // CHECK: operator Bar()  /* Test 2 */ const {
-    Foo foo;                            // CHECK: Bar foo;
-    return foo;
-  }
-};
-
-int main() {
-  Baz boo;
-  Foo foo = static_cast<Foo>(boo);      // CHECK: Bar foo = static_cast<Bar>(boo);
-  return 0;
-}
-
-// Test 1.
-// RUN: clang-rename -offset=7 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
-// Test 2.
-// RUN: clang-rename -offset=164 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
-
-// To find offsets after modifying the file, use:
-//   grep -Ubo 'Foo.*' <file>
diff --git a/test/clang-rename/Variable.cpp b/test/clang-rename/Variable.cpp
deleted file mode 100644
index d7e670f..0000000
--- a/test/clang-rename/Variable.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-#define NAMESPACE namespace A
-NAMESPACE {
-int Foo;          /* Test 1 */        // CHECK: int Bar;
-}
-int Foo;                              // CHECK: int Foo;
-int Qux = Foo;                        // CHECK: int Qux = Foo;
-int Baz = A::Foo; /* Test 2 */        // CHECK: Baz = A::Bar;
-void fun() {
-  struct {
-    int Foo;                          // CHECK: int Foo;
-  } b = {100};
-  int Foo = 100;                      // CHECK: int Foo = 100;
-  Baz = Foo;                          // CHECK: Baz = Foo;
-  {
-    extern int Foo;                   // CHECK: extern int Foo;
-    Baz = Foo;                        // CHECK: Baz = Foo;
-    Foo = A::Foo /* Test 3 */ + Baz;  // CHECK: Foo = A::Bar /* Test 3 */ + Baz;
-    A::Foo /* Test 4 */ = b.Foo;      // CHECK: A::Bar /* Test 4 */ = b.Foo;
-  }
-  Foo = b.Foo;                        // Foo = b.Foo;
-}
-
-// Test 1.
-// RUN: clang-rename -offset=46 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
-// Test 2.
-// RUN: clang-rename -offset=234 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
-// Test 3.
-// RUN: clang-rename -offset=641 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
-// Test 4.
-// RUN: clang-rename -offset=716 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
-
-// To find offsets after modifying the file, use:
-//   grep -Ubo 'Foo.*' <file>
diff --git a/test/clang-rename/VariableMacro.cpp b/test/clang-rename/VariableMacro.cpp
deleted file mode 100644
index 622e825..0000000
--- a/test/clang-rename/VariableMacro.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-#define Baz Foo // CHECK: #define Baz Bar
-
-void foo(int value) {}
-
-void macro() {
-  int Foo;  /* Test 1 */  // CHECK: int Bar;
-  Foo = 42; /* Test 2 */  // CHECK: Bar = 42;
-  Baz -= 0;
-  foo(Foo); /* Test 3 */  // CHECK: foo(Bar);
-  foo(Baz);
-}
-
-// Test 1.
-// RUN: clang-rename -offset=88 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
-// Test 2.
-// RUN: clang-rename -offset=129 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
-// Test 3.
-// RUN: clang-rename -offset=191 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
-
-// To find offsets after modifying the file, use:
-//   grep -Ubo 'Foo.*' <file>
diff --git a/test/clang-rename/YAMLInput.cpp b/test/clang-rename/YAMLInput.cpp
deleted file mode 100644
index 55dbc6d..0000000
--- a/test/clang-rename/YAMLInput.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-class Foo1 { // CHECK: class Bar1
-};
-
-class Foo2 { // CHECK: class Bar2
-};
-
-// Test 1.
-// RUN: clang-rename -input %S/Inputs/OffsetToNewName.yaml %s -- | sed 's,//.*,,' | FileCheck %s
-// Test 2.
-// RUN: clang-rename -input %S/Inputs/QualifiedNameToNewName.yaml %s -- | sed 's,//.*,,' | FileCheck %s
diff --git a/test/clang-reorder-fields/ClassDerived.cpp b/test/clang-reorder-fields/ClassDerived.cpp
new file mode 100644
index 0000000..e7e9ac1
--- /dev/null
+++ b/test/clang-reorder-fields/ClassDerived.cpp
@@ -0,0 +1,33 @@
+// RUN: clang-reorder-fields -record-name bar::Derived -fields-order z,y %s -- | FileCheck %s
+
+namespace bar {
+class Base {
+public:
+  Base(int nx, int np) : x(nx), p(np) {}
+  int x;
+  int p;
+};
+
+
+class Derived : public Base {
+public:
+  Derived(long ny);
+  Derived(char nz);
+private:
+  long y;
+  char z;
+};
+
+Derived::Derived(long ny) : 
+    Base(ny, 0),
+    y(ny),                   // CHECK:       {{^  z\(static_cast<char>\(ny\)\),}}
+    z(static_cast<char>(ny)) // CHECK-NEXT:  {{^  y\(ny\)}}
+{}
+
+Derived::Derived(char nz) : 
+    Base(1, 2),
+    y(nz),  // CHECK:       {{^  z\(x\),}}
+    z(x)    // CHECK-NEXT:  {{^  y\(nz\)}}
+{}
+
+} // namespace bar
diff --git a/test/clang-reorder-fields/FieldDependencyWarning.cpp b/test/clang-reorder-fields/FieldDependencyWarning.cpp
new file mode 100644
index 0000000..bbe0e7f
--- /dev/null
+++ b/test/clang-reorder-fields/FieldDependencyWarning.cpp
@@ -0,0 +1,54 @@
+// RUN: clang-reorder-fields -record-name bar::Foo -fields-order y,z,c,x %s -- 2>&1 | FileCheck --check-prefix=CHECK-MESSAGES %s
+// FIXME: clang-reorder-fields should provide -verify mode to make writing these checks
+// easier and more accurate, for now we follow clang-tidy's approach.
+
+namespace bar {
+
+struct Dummy {
+  Dummy(int x, char c) : x(x), c(c) {}
+  int x;
+  char c;
+};
+
+class Foo {
+public:
+  Foo(int x, double y, char cin);
+  Foo(int nx);
+  Foo();
+  int x;
+  double y;
+  char c;
+  Dummy z;
+};
+
+static char bar(char c) {
+  return c + 1;
+}
+
+Foo::Foo() : x(), y(), c(), z(0, 'a') {}
+
+Foo::Foo(int x, double y, char cin) :  
+  x(x),                 
+  y(y),                 
+  c(cin),               
+  z(this->x, bar(c))    
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: reordering field x after z makes x uninitialized when used in init expression
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: reordering field c after z makes c uninitialized when used in init expression
+{}
+
+Foo::Foo(int nx) :
+  x(nx),              
+  y(x),
+  c(0),            
+  z(bar(bar(x)), c)     
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: reordering field x after y makes x uninitialized when used in init expression
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: reordering field x after z makes x uninitialized when used in init expression
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: reordering field c after z makes c uninitialized when used in init expression
+{}
+
+} // namespace bar
+
+int main() {
+  bar::Foo F(5, 12.8, 'c');
+  return 0;
+}
diff --git a/test/clang-reorder-fields/FieldDependencyWarningDerived.cpp b/test/clang-reorder-fields/FieldDependencyWarningDerived.cpp
new file mode 100644
index 0000000..bbc58ae
--- /dev/null
+++ b/test/clang-reorder-fields/FieldDependencyWarningDerived.cpp
@@ -0,0 +1,36 @@
+// RUN: clang-reorder-fields -record-name bar::Derived -fields-order z,y %s -- 2>&1 | FileCheck --check-prefix=CHECK-MESSAGES %s
+// FIXME: clang-reorder-fields should provide -verify mode to make writing these checks
+// easier and more accurate, for now we follow clang-tidy's approach.
+
+namespace bar {
+struct Base {
+  int x;
+  int p;
+};
+
+class Derived : public Base {
+public:
+  Derived(long ny);
+  Derived(char nz);
+private:
+  long y;
+  char z;
+};
+
+Derived::Derived(long ny) : 
+  Base(),
+  y(ny), 
+  z(static_cast<char>(y)) 
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: reordering field y after z makes y uninitialized when used in init expression
+{}
+
+Derived::Derived(char nz) : 
+  Base(),
+  y(nz),
+  // Check that base class fields are correctly ignored in reordering checks
+  // x has field index 1 and so would improperly warn if this wasn't the case since the command for this file swaps field indexes 1 and 2
+  z(x) 
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: reordering field x after z makes x uninitialized when used in init expression
+{}
+
+} // namespace bar
diff --git a/test/clang-reorder-fields/PlainCStructFieldsOrder.c b/test/clang-reorder-fields/PlainCStructFieldsOrder.c
new file mode 100644
index 0000000..5b4fe9e
--- /dev/null
+++ b/test/clang-reorder-fields/PlainCStructFieldsOrder.c
@@ -0,0 +1,14 @@
+// RUN: clang-reorder-fields -record-name Foo -fields-order z,w,y,x %s -- | FileCheck %s
+
+struct Foo {
+  const int* x; // CHECK:      {{^  double z;}}
+  int y;        // CHECK-NEXT: {{^  int w;}}
+  double z;     // CHECK-NEXT: {{^  int y;}}
+  int w;        // CHECK-NEXT: {{^  const int\* x}}
+};
+
+int main() {
+  const int x = 13;
+  struct Foo foo = { &x, 0, 1.29, 17 }; // CHECK: {{^  struct Foo foo = { 1.29, 17, 0, &x };}} 
+  return 0;
+}
diff --git a/test/clang-tidy/Inputs/modernize-smart-ptr/initializer_list.h b/test/clang-tidy/Inputs/modernize-smart-ptr/initializer_list.h
new file mode 100644
index 0000000..f189262
--- /dev/null
+++ b/test/clang-tidy/Inputs/modernize-smart-ptr/initializer_list.h
@@ -0,0 +1,31 @@
+namespace std {
+typedef decltype(sizeof(int)) size_t;
+
+template <class _E> class initializer_list {
+  const _E *__begin_;
+  size_t __size_;
+
+  initializer_list(const _E *__b, size_t __s) : __begin_(__b), __size_(__s) {}
+
+public:
+  typedef _E value_type;
+  typedef const _E &reference;
+  typedef const _E &const_reference;
+  typedef size_t size_type;
+
+  typedef const _E *iterator;
+  typedef const _E *const_iterator;
+
+  initializer_list() : __begin_(nullptr), __size_(0) {}
+
+  size_t size() const { return __size_; }
+  const _E *begin() const { return __begin_; }
+  const _E *end() const { return __begin_ + __size_; }
+};
+
+template <class _E>
+class vector {
+ public:
+  vector(initializer_list<_E> init);
+};
+} // namespace std
diff --git a/test/clang-tidy/Inputs/modernize-smart-ptr/shared_ptr.h b/test/clang-tidy/Inputs/modernize-smart-ptr/shared_ptr.h
new file mode 100644
index 0000000..0f4f2a9
--- /dev/null
+++ b/test/clang-tidy/Inputs/modernize-smart-ptr/shared_ptr.h
@@ -0,0 +1,24 @@
+namespace std {
+
+template <typename type>
+class shared_ptr {
+public:
+  shared_ptr();
+  shared_ptr(type *ptr);
+  shared_ptr(const shared_ptr<type> &t) {}
+  shared_ptr(shared_ptr<type> &&t) {}
+  ~shared_ptr();
+  type &operator*() { return *ptr; }
+  type *operator->() { return ptr; }
+  type *release();
+  void reset();
+  void reset(type *pt);
+  shared_ptr &operator=(shared_ptr &&);
+  template <typename T>
+  shared_ptr &operator=(shared_ptr<T> &&);
+
+private:
+  type *ptr;
+};
+
+}  // namespace std
diff --git a/test/clang-tidy/Inputs/modernize-smart-ptr/unique_ptr.h b/test/clang-tidy/Inputs/modernize-smart-ptr/unique_ptr.h
new file mode 100644
index 0000000..5dc9e02
--- /dev/null
+++ b/test/clang-tidy/Inputs/modernize-smart-ptr/unique_ptr.h
@@ -0,0 +1,28 @@
+namespace std {
+
+template <typename T>
+class default_delete {};
+
+template <typename type, typename Deleter = std::default_delete<type>>
+class unique_ptr {
+public:
+  unique_ptr() {}
+  unique_ptr(type *ptr) {}
+  unique_ptr(const unique_ptr<type> &t) = delete;
+  unique_ptr(unique_ptr<type> &&t) {}
+  ~unique_ptr() {}
+  type &operator*() { return *ptr; }
+  type *operator->() { return ptr; }
+  type *release() { return ptr; }
+  void reset() {}
+  void reset(type *pt) {}
+  void reset(type pt) {}
+  unique_ptr &operator=(unique_ptr &&) { return *this; }
+  template <typename T>
+  unique_ptr &operator=(unique_ptr<T> &&) { return *this; }
+
+private:
+  type *ptr;
+};
+
+}  // namespace std
diff --git a/test/clang-tidy/Inputs/performance-unnecessary-value-param/header-fixed.h b/test/clang-tidy/Inputs/performance-unnecessary-value-param/header-fixed.h
new file mode 100644
index 0000000..f3e9e72
--- /dev/null
+++ b/test/clang-tidy/Inputs/performance-unnecessary-value-param/header-fixed.h
@@ -0,0 +1,15 @@
+// struct ABC is expensive to copy and should be
+// passed as a const referece.
+struct ABC {
+  ABC(const ABC&);
+  int get(int) const;
+};
+
+
+int f1(int n,              const ABC& v1,   const ABC& v2); // line 9
+
+int f1(int n, ABC v1); // line 11
+
+
+
+int f2(        int n,       const ABC& v2); // line 15
diff --git a/test/clang-tidy/Inputs/performance-unnecessary-value-param/header.h b/test/clang-tidy/Inputs/performance-unnecessary-value-param/header.h
new file mode 100644
index 0000000..3f55c79
--- /dev/null
+++ b/test/clang-tidy/Inputs/performance-unnecessary-value-param/header.h
@@ -0,0 +1,15 @@
+// struct ABC is expensive to copy and should be
+// passed as a const referece.
+struct ABC {
+  ABC(const ABC&);
+  int get(int) const;
+};
+
+
+int f1(int n,              ABC v1,   ABC v2); // line 9
+
+int f1(int n, ABC v1); // line 11
+
+
+
+int f2(        int n,       ABC v2); // line 15
diff --git a/test/clang-tidy/android-cloexec-accept.cpp b/test/clang-tidy/android-cloexec-accept.cpp
new file mode 100644
index 0000000..9990594
--- /dev/null
+++ b/test/clang-tidy/android-cloexec-accept.cpp
@@ -0,0 +1,28 @@
+// RUN: %check_clang_tidy %s android-cloexec-accept %t
+
+struct sockaddr {};
+typedef int socklen_t;
+#define NULL 0
+
+extern "C" int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+
+void f() {
+  accept(0, NULL, NULL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer accept4() to accept() because accept4() allows SOCK_CLOEXEC [android-cloexec-accept]
+  // CHECK-FIXES: accept4(0, NULL, NULL, SOCK_CLOEXEC);
+}
+
+namespace i {
+int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+void g() {
+  accept(0, NULL, NULL);
+}
+} // namespace i
+
+class C {
+public:
+  int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+  void h() {
+    accept(0, NULL, NULL);
+  }
+};
diff --git a/test/clang-tidy/android-cloexec-accept4.cpp b/test/clang-tidy/android-cloexec-accept4.cpp
new file mode 100644
index 0000000..448d4a9
--- /dev/null
+++ b/test/clang-tidy/android-cloexec-accept4.cpp
@@ -0,0 +1,66 @@
+// RUN: %check_clang_tidy %s android-cloexec-accept4 %t
+
+typedef int socklen_t;
+struct sockaddr {};
+
+#define SOCK_NONBLOCK 1
+#define __O_CLOEXEC 3
+#define SOCK_CLOEXEC __O_CLOEXEC
+#define TEMP_FAILURE_RETRY(exp) \
+  ({                            \
+    int _rc;                    \
+    do {                        \
+      _rc = (exp);              \
+    } while (_rc == -1);        \
+  })
+#define NULL 0
+
+extern "C" int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
+
+void a() {
+  accept4(0, NULL, NULL, SOCK_NONBLOCK);
+  // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: 'accept4' should use SOCK_CLOEXEC where possible [android-cloexec-accept4]
+  // CHECK-FIXES: accept4(0, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC);
+  TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, SOCK_NONBLOCK));
+  // CHECK-MESSAGES: :[[@LINE-1]]:58: warning: 'accept4'
+  // CHECK-FIXES: TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC));
+}
+
+void f() {
+  accept4(0, NULL, NULL, 3);
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: 'accept4'
+  // CHECK-FIXES: accept4(0, NULL, NULL, 3 | SOCK_CLOEXEC);
+  TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, 3));
+  // CHECK-MESSAGES: :[[@LINE-1]]:46: warning: 'accept4'
+  // CHECK-FIXES: TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, 3 | SOCK_CLOEXEC));
+
+  int flag = SOCK_NONBLOCK;
+  accept4(0, NULL, NULL, flag);
+  TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, flag));
+}
+
+namespace i {
+int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
+
+void d() {
+  accept4(0, NULL, NULL, SOCK_NONBLOCK);
+  TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, SOCK_NONBLOCK));
+}
+
+} // namespace i
+
+void e() {
+  accept4(0, NULL, NULL, SOCK_CLOEXEC);
+  TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, SOCK_CLOEXEC));
+  accept4(0, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC);
+  TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC));
+}
+
+class G {
+public:
+  int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
+  void d() {
+    accept4(0, NULL, NULL, SOCK_NONBLOCK);
+    TEMP_FAILURE_RETRY(accept4(0, NULL, NULL, SOCK_NONBLOCK));
+  }
+};
diff --git a/test/clang-tidy/android-cloexec-creat.cpp b/test/clang-tidy/android-cloexec-creat.cpp
new file mode 100644
index 0000000..df57b10
--- /dev/null
+++ b/test/clang-tidy/android-cloexec-creat.cpp
@@ -0,0 +1,35 @@
+// RUN: %check_clang_tidy %s android-cloexec-creat %t
+
+typedef int mode_t;
+
+extern "C" int creat(const char *path, mode_t, ...);
+extern "C" int create(const char *path, mode_t, ...);
+
+void f() {
+  creat("filename", 0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer open() to creat() because open() allows O_CLOEXEC [android-cloexec-creat]
+  // CHECK-FIXES: open ("filename", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0);
+  create("filename", 0);
+  // CHECK-MESSAGES-NOT: warning:
+  mode_t mode = 0755;
+  creat("filename", mode);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning:
+  // CHECK-FIXES: open ("filename", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode);
+}
+
+namespace i {
+int creat(const char *path, mode_t, ...);
+void g() {
+  creat("filename", 0);
+  // CHECK-MESSAGES-NOT: warning:
+}
+} // namespace i
+
+class C {
+public:
+  int creat(const char *path, mode_t, ...);
+  void h() {
+    creat("filename", 0);
+    // CHECK-MESSAGES-NOT: warning:
+  }
+};
diff --git a/test/clang-tidy/android-cloexec-dup.cpp b/test/clang-tidy/android-cloexec-dup.cpp
new file mode 100644
index 0000000..f7011b8
--- /dev/null
+++ b/test/clang-tidy/android-cloexec-dup.cpp
@@ -0,0 +1,31 @@
+// RUN: %check_clang_tidy %s android-cloexec-dup %t
+
+extern "C" int dup(int oldfd);
+void f() {
+  dup(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer fcntl() to dup() because fcntl() allows F_DUPFD_CLOEXEC [android-cloexec-dup]
+  // CHECK-FIXES: fcntl(1, F_DUPFD_CLOEXEC);
+  int oldfd = 0;
+  dup(oldfd);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer
+  // CHECK-FIXES: fcntl(oldfd, F_DUPFD_CLOEXEC);
+}
+
+namespace i {
+int dup(int oldfd);
+void g() {
+  dup(0);
+  int oldfd = 1;
+  dup(oldfd);
+}
+} // namespace i
+
+class C {
+public:
+  int dup(int oldfd);
+  void h() {
+    dup(0);
+    int oldfd = 1;
+    dup(oldfd);
+  }
+};
diff --git a/test/clang-tidy/android-cloexec-epoll-create.cpp b/test/clang-tidy/android-cloexec-epoll-create.cpp
new file mode 100644
index 0000000..d58e493
--- /dev/null
+++ b/test/clang-tidy/android-cloexec-epoll-create.cpp
@@ -0,0 +1,24 @@
+// RUN: %check_clang_tidy %s android-cloexec-epoll-create %t
+
+extern "C" int epoll_create(int size);
+
+void f() {
+  epoll_create(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer epoll_create() to epoll_create1() because epoll_create1() allows EPOLL_CLOEXEC [android-cloexec-epoll-create]
+  // CHECK-FIXES: epoll_create1(EPOLL_CLOEXEC);
+}
+
+namespace i {
+int epoll_create(int size);
+void g() {
+  epoll_create(0);
+}
+} // namespace i
+
+class C {
+public:
+  int epoll_create(int size);
+  void h() {
+    epoll_create(0);
+  }
+};
diff --git a/test/clang-tidy/android-cloexec-epoll-create1.cpp b/test/clang-tidy/android-cloexec-epoll-create1.cpp
new file mode 100644
index 0000000..696a20c
--- /dev/null
+++ b/test/clang-tidy/android-cloexec-epoll-create1.cpp
@@ -0,0 +1,59 @@
+// RUN: %check_clang_tidy %s android-cloexec-epoll-create1 %t
+
+#define __O_CLOEXEC 3
+#define EPOLL_CLOEXEC __O_CLOEXEC
+#define TEMP_FAILURE_RETRY(exp) \
+  ({                            \
+    int _rc;                    \
+    do {                        \
+      _rc = (exp);              \
+    } while (_rc == -1);        \
+  })
+
+extern "C" int epoll_create1(int flags);
+
+void a() {
+  epoll_create1(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 'epoll_create1' should use EPOLL_CLOEXEC where possible [android-cloexec-epoll-create1]
+  // CHECK-FIXES: epoll_create1(EPOLL_CLOEXEC);
+  TEMP_FAILURE_RETRY(epoll_create1(0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: 'epoll_create1'
+  // CHECK-FIXES: TEMP_FAILURE_RETRY(epoll_create1(EPOLL_CLOEXEC));
+}
+
+void f() {
+  epoll_create1(3);
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 'epoll_create1'
+  // CHECK-FIXES: epoll_create1(EPOLL_CLOEXEC);
+  TEMP_FAILURE_RETRY(epoll_create1(3));
+  // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: 'epoll_create1'
+  // CHECK-FIXES: TEMP_FAILURE_RETRY(epoll_create1(EPOLL_CLOEXEC));
+
+  int flag = 0;
+  epoll_create1(EPOLL_CLOEXEC);
+  TEMP_FAILURE_RETRY(epoll_create1(EPOLL_CLOEXEC));
+}
+
+namespace i {
+int epoll_create1(int flags);
+
+void d() {
+  epoll_create1(0);
+  TEMP_FAILURE_RETRY(epoll_create1(0));
+}
+
+} // namespace i
+
+void e() {
+  epoll_create1(EPOLL_CLOEXEC);
+  TEMP_FAILURE_RETRY(epoll_create1(EPOLL_CLOEXEC));
+}
+
+class G {
+public:
+  int epoll_create1(int flags);
+  void d() {
+    epoll_create1(EPOLL_CLOEXEC);
+    TEMP_FAILURE_RETRY(epoll_create1(EPOLL_CLOEXEC));
+  }
+};
diff --git a/test/clang-tidy/android-cloexec-fopen.cpp b/test/clang-tidy/android-cloexec-fopen.cpp
new file mode 100644
index 0000000..6b6c655
--- /dev/null
+++ b/test/clang-tidy/android-cloexec-fopen.cpp
@@ -0,0 +1,57 @@
+// RUN: %check_clang_tidy %s android-cloexec-fopen %t
+
+#define FILE_OPEN_RO "r"
+
+typedef int FILE;
+
+extern "C" FILE *fopen(const char *filename, const char *mode, ...);
+extern "C" FILE *open(const char *filename, const char *mode, ...);
+
+void f() {
+  fopen("filename", "r");
+  // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use 'fopen' mode 'e' to set O_CLOEXEC [android-cloexec-fopen]
+  // CHECK-FIXES: fopen("filename", "re");
+
+  fopen("filename", FILE_OPEN_RO);
+  // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use 'fopen' mode 'e'
+  // CHECK-FIXES: fopen("filename", FILE_OPEN_RO "e");
+
+  fopen("filename", "er");
+  // CHECK-MESSAGES-NOT: warning:
+  fopen("filename", "re");
+  // CHECK-MESSAGES-NOT: warning:
+  fopen("filename", "e");
+  // CHECK-MESSAGES-NOT: warning:
+  open("filename", "e");
+  // CHECK-MESSAGES-NOT: warning:
+
+  char *str = "r";
+  fopen("filename", str);
+  // CHECK-MESSAGES-NOT: warning:
+  str = "re";
+  fopen("filename", str);
+  // CHECK-MESSAGES-NOT: warning:
+  char arr[2] = "r";
+  fopen("filename", arr);
+  // CHECK-MESSAGES-NOT: warning:
+  char arr2[3] = "re";
+  fopen("filename", arr2);
+  // CHECK-MESSAGES-NOT: warning:
+}
+
+namespace i {
+int *fopen(const char *filename, const char *mode, ...);
+void g() {
+  fopen("filename", "e");
+  // CHECK-MESSAGES-NOT: warning:
+}
+} // namespace i
+
+class C {
+public:
+  int *fopen(const char *filename, const char *mode, ...);
+  void h() {
+    fopen("filename", "e");
+    // CHECK-MESSAGES-NOT: warning:
+  }
+};
diff --git a/test/clang-tidy/android-cloexec-inotify-init.cpp b/test/clang-tidy/android-cloexec-inotify-init.cpp
new file mode 100644
index 0000000..01eb51e
--- /dev/null
+++ b/test/clang-tidy/android-cloexec-inotify-init.cpp
@@ -0,0 +1,24 @@
+// RUN: %check_clang_tidy %s android-cloexec-inotify-init %t
+
+extern "C" int inotify_init();
+
+void f() {
+  inotify_init();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer inotify_init() to inotify_init1() because inotify_init1() allows IN_CLOEXEC [android-cloexec-inotify-init]
+  // CHECK-FIXES: inotify_init1(IN_CLOEXEC);
+}
+
+namespace i {
+int inotify_init();
+void g() {
+  inotify_init();
+}
+} // namespace i
+
+class C {
+public:
+  int inotify_init();
+  void h() {
+    inotify_init();
+  }
+};
diff --git a/test/clang-tidy/android-cloexec-inotify-init1.cpp b/test/clang-tidy/android-cloexec-inotify-init1.cpp
new file mode 100644
index 0000000..2b74fad
--- /dev/null
+++ b/test/clang-tidy/android-cloexec-inotify-init1.cpp
@@ -0,0 +1,64 @@
+// RUN: %check_clang_tidy %s android-cloexec-inotify-init1 %t
+
+#define IN_NONBLOCK 1
+#define __O_CLOEXEC 3
+#define IN_CLOEXEC __O_CLOEXEC
+#define TEMP_FAILURE_RETRY(exp) \
+  ({                            \
+    int _rc;                    \
+    do {                        \
+      _rc = (exp);              \
+    } while (_rc == -1);        \
+  })
+
+extern "C" int inotify_init1(int flags);
+
+void a() {
+  inotify_init1(IN_NONBLOCK);
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: 'inotify_init1' should use IN_CLOEXEC where possible [android-cloexec-inotify-init1]
+  // CHECK-FIXES: inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
+  TEMP_FAILURE_RETRY(inotify_init1(IN_NONBLOCK));
+  // CHECK-MESSAGES: :[[@LINE-1]]:47: warning: 'inotify_init1'
+  // CHECK-FIXES: TEMP_FAILURE_RETRY(inotify_init1(IN_NONBLOCK | IN_CLOEXEC));
+}
+
+void f() {
+  inotify_init1(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 'inotify_init1'
+  // CHECK-FIXES: inotify_init1(IN_CLOEXEC);
+  TEMP_FAILURE_RETRY(inotify_init1(0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: 'inotify_init1'
+  // CHECK-FIXES: TEMP_FAILURE_RETRY(inotify_init1(IN_CLOEXEC));
+
+  int flag = 1;
+  inotify_init1(flag);
+  TEMP_FAILURE_RETRY(inotify_init1(flag));
+}
+
+namespace i {
+int inotify_init1(int flags);
+
+void d() {
+  inotify_init1(IN_NONBLOCK);
+  TEMP_FAILURE_RETRY(inotify_init1(IN_NONBLOCK));
+}
+
+} // namespace i
+
+void e() {
+  inotify_init1(IN_CLOEXEC);
+  TEMP_FAILURE_RETRY(inotify_init1(IN_CLOEXEC));
+  inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
+  TEMP_FAILURE_RETRY(inotify_init1(IN_NONBLOCK | IN_CLOEXEC));
+}
+
+class G {
+public:
+  int inotify_init1(int flags);
+  void d() {
+    inotify_init1(IN_CLOEXEC);
+    TEMP_FAILURE_RETRY(inotify_init1(IN_CLOEXEC));
+    inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
+    TEMP_FAILURE_RETRY(inotify_init1(IN_NONBLOCK | IN_CLOEXEC));
+  }
+};
diff --git a/test/clang-tidy/android-cloexec-memfd-create.cpp b/test/clang-tidy/android-cloexec-memfd-create.cpp
new file mode 100644
index 0000000..a8dafd5
--- /dev/null
+++ b/test/clang-tidy/android-cloexec-memfd-create.cpp
@@ -0,0 +1,63 @@
+// RUN: %check_clang_tidy %s android-cloexec-memfd-create %t
+
+#define MFD_ALLOW_SEALING 1
+#define __O_CLOEXEC 3
+#define MFD_CLOEXEC __O_CLOEXEC
+#define TEMP_FAILURE_RETRY(exp) \
+  ({                            \
+    int _rc;                    \
+    do {                        \
+      _rc = (exp);              \
+    } while (_rc == -1);        \
+  })
+#define NULL 0
+
+extern "C" int memfd_create(const char *name, unsigned int flags);
+
+void a() {
+  memfd_create(NULL, MFD_ALLOW_SEALING);
+  // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: 'memfd_create' should use MFD_CLOEXEC where possible [android-cloexec-memfd-create]
+  // CHECK-FIXES: memfd_create(NULL, MFD_ALLOW_SEALING | MFD_CLOEXEC)
+  TEMP_FAILURE_RETRY(memfd_create(NULL, MFD_ALLOW_SEALING));
+  // CHECK-MESSAGES: :[[@LINE-1]]:58: warning: 'memfd_create'
+  // CHECK-FIXES: TEMP_FAILURE_RETRY(memfd_create(NULL, MFD_ALLOW_SEALING | MFD_CLOEXEC))
+}
+
+void f() {
+  memfd_create(NULL, 3);
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: 'memfd_create'
+  // CHECK-FIXES: memfd_create(NULL, 3 | MFD_CLOEXEC)
+  TEMP_FAILURE_RETRY(memfd_create(NULL, 3));
+  // CHECK-MESSAGES: :[[@LINE-1]]:42: warning: 'memfd_create'
+  // CHECK-FIXES: TEMP_FAILURE_RETRY(memfd_create(NULL, 3 | MFD_CLOEXEC))
+
+  int flag = 3;
+  memfd_create(NULL, flag);
+  TEMP_FAILURE_RETRY(memfd_create(NULL, flag));
+}
+
+namespace i {
+int memfd_create(const char *name, unsigned int flags);
+
+void d() {
+  memfd_create(NULL, MFD_ALLOW_SEALING);
+  TEMP_FAILURE_RETRY(memfd_create(NULL, MFD_ALLOW_SEALING));
+}
+
+} // namespace i
+
+void e() {
+  memfd_create(NULL, MFD_CLOEXEC);
+  TEMP_FAILURE_RETRY(memfd_create(NULL, MFD_CLOEXEC));
+  memfd_create(NULL, MFD_ALLOW_SEALING | MFD_CLOEXEC);
+  TEMP_FAILURE_RETRY(memfd_create(NULL, MFD_ALLOW_SEALING | MFD_CLOEXEC));
+}
+
+class G {
+public:
+  int memfd_create(const char *name, unsigned int flags);
+  void d() {
+    memfd_create(NULL, MFD_ALLOW_SEALING);
+    TEMP_FAILURE_RETRY(memfd_create(NULL, MFD_ALLOW_SEALING));
+  }
+};
diff --git a/test/clang-tidy/android-cloexec-open.cpp b/test/clang-tidy/android-cloexec-open.cpp
new file mode 100644
index 0000000..4ef1f40
--- /dev/null
+++ b/test/clang-tidy/android-cloexec-open.cpp
@@ -0,0 +1,180 @@
+// RUN: %check_clang_tidy %s android-cloexec-open %t
+
+#define O_RDWR 1
+#define O_EXCL 2
+#define __O_CLOEXEC 3
+#define O_CLOEXEC __O_CLOEXEC
+#define TEMP_FAILURE_RETRY(exp) \
+  ({                            \
+    int _rc;                    \
+    do {                        \
+      _rc = (exp);              \
+    } while (_rc == -1);        \
+  })
+
+extern "C" int open(const char *fn, int flags, ...);
+extern "C" int open64(const char *fn, int flags, ...);
+extern "C" int openat(int dirfd, const char *pathname, int flags, ...);
+
+void a() {
+  open("filename", O_RDWR);
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: 'open' should use O_CLOEXEC where possible [android-cloexec-open]
+  // CHECK-FIXES: O_RDWR | O_CLOEXEC
+  TEMP_FAILURE_RETRY(open("filename", O_RDWR));
+  // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: 'open' should use O_CLOEXEC where
+  // CHECK-FIXES: O_RDWR | O_CLOEXEC
+  open("filename", O_RDWR | O_EXCL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: 'open' should use O_CLOEXEC where
+  // CHECK-FIXES: O_RDWR | O_EXCL | O_CLOEXEC
+  TEMP_FAILURE_RETRY(open("filename", O_RDWR | O_EXCL));
+  // CHECK-MESSAGES: :[[@LINE-1]]:54: warning: 'open' should use O_CLOEXEC where
+  // CHECK-FIXES: O_RDWR | O_EXCL | O_CLOEXEC
+}
+
+void b() {
+  open64("filename", O_RDWR);
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: 'open64' should use O_CLOEXEC where possible [android-cloexec-open]
+  // CHECK-FIXES: O_RDWR | O_CLOEXEC
+  TEMP_FAILURE_RETRY(open64("filename", O_RDWR));
+  // CHECK-MESSAGES: :[[@LINE-1]]:47: warning: 'open64' should use O_CLOEXEC where
+  // CHECK-FIXES: O_RDWR | O_CLOEXEC
+  open64("filename", O_RDWR | O_EXCL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: 'open64' should use O_CLOEXEC where
+  // CHECK-FIXES: O_RDWR | O_EXCL | O_CLOEXEC
+  TEMP_FAILURE_RETRY(open64("filename", O_RDWR | O_EXCL));
+  // CHECK-MESSAGES: :[[@LINE-1]]:56: warning: 'open64' should use O_CLOEXEC where
+  // CHECK-FIXES: O_RDWR | O_EXCL | O_CLOEXEC
+}
+
+void c() {
+  openat(0, "filename", O_RDWR);
+  // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: 'openat' should use O_CLOEXEC where possible [android-cloexec-open]
+  // CHECK-FIXES: O_RDWR | O_CLOEXEC
+  TEMP_FAILURE_RETRY(openat(0, "filename", O_RDWR));
+  // CHECK-MESSAGES: :[[@LINE-1]]:50: warning: 'openat' should use O_CLOEXEC where
+  // CHECK-FIXES: O_RDWR | O_CLOEXEC
+  openat(0, "filename", O_RDWR | O_EXCL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: 'openat' should use O_CLOEXEC where
+  // CHECK-FIXES: O_RDWR | O_EXCL | O_CLOEXEC
+  TEMP_FAILURE_RETRY(openat(0, "filename", O_RDWR | O_EXCL));
+  // CHECK-MESSAGES: :[[@LINE-1]]:59: warning: 'openat' should use O_CLOEXEC where
+  // CHECK-FIXES: O_RDWR | O_EXCL | O_CLOEXEC
+}
+
+void f() {
+  open("filename", 3);
+  // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: 'open' should use O_CLOEXEC where possible [android-cloexec-open]
+  // CHECK-FIXES: 3 | O_CLOEXEC
+  TEMP_FAILURE_RETRY(open("filename", 3));
+  // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: 'open' should use O_CLOEXEC where
+  // CHECK-FIXES: 3 | O_CLOEXEC
+  open64("filename", 3);
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: 'open64' should use O_CLOEXEC where possible [android-cloexec-open]
+  // CHECK-FIXES: 3 | O_CLOEXEC
+  TEMP_FAILURE_RETRY(open64("filename", 3));
+  // CHECK-MESSAGES: :[[@LINE-1]]:42: warning: 'open64' should use O_CLOEXEC where
+  // CHECK-FIXES: 3 | O_CLOEXEC
+  openat(0, "filename", 3);
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: 'openat' should use O_CLOEXEC where possible [android-cloexec-open]
+  // CHECK-FIXES: 3 | O_CLOEXEC
+  TEMP_FAILURE_RETRY(openat(0, "filename", 3));
+  // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: 'openat' should use O_CLOEXEC where
+  // CHECK-FIXES: 3 | O_CLOEXEC
+
+  int flag = 3;
+  open("filename", flag);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(open("filename", flag));
+  // CHECK-MESSAGES-NOT: warning:
+  open64("filename", flag);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(open64("filename", flag));
+  // CHECK-MESSAGES-NOT: warning:
+  openat(0, "filename", flag);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(openat(0, "filename", flag));
+  // CHECK-MESSAGES-NOT: warning:
+}
+
+namespace i {
+int open(const char *pathname, int flags, ...);
+int open64(const char *pathname, int flags, ...);
+int openat(int dirfd, const char *pathname, int flags, ...);
+
+void d() {
+  open("filename", O_RDWR);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(open("filename", O_RDWR));
+  // CHECK-MESSAGES-NOT: warning:
+  open64("filename", O_RDWR);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(open64("filename", O_RDWR));
+  // CHECK-MESSAGES-NOT: warning:
+  openat(0, "filename", O_RDWR);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(openat(0, "filename", O_RDWR));
+  // CHECK-MESSAGES-NOT: warning:
+}
+
+} // namespace i
+
+void e() {
+  open("filename", O_CLOEXEC);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(open("filename", O_CLOEXEC));
+  // CHECK-MESSAGES-NOT: warning:
+  open("filename", O_RDWR | O_CLOEXEC);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(open("filename", O_RDWR | O_CLOEXEC));
+  // CHECK-MESSAGES-NOT: warning:
+  open("filename", O_RDWR | O_CLOEXEC | O_EXCL);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(open("filename", O_RDWR | O_CLOEXEC | O_EXCL));
+  // CHECK-MESSAGES-NOT: warning:
+  open64("filename", O_CLOEXEC);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(open64("filename", O_CLOEXEC));
+  // CHECK-MESSAGES-NOT: warning:
+  open64("filename", O_RDWR | O_CLOEXEC);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(open64("filename", O_RDWR | O_CLOEXEC));
+  // CHECK-MESSAGES-NOT: warning:
+  open64("filename", O_RDWR | O_CLOEXEC | O_EXCL);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(open64("filename", O_RDWR | O_CLOEXEC | O_EXCL));
+  // CHECK-MESSAGES-NOT: warning:
+  openat(0, "filename", O_CLOEXEC);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(openat(0, "filename", O_CLOEXEC));
+  // CHECK-MESSAGES-NOT: warning:
+  openat(0, "filename", O_RDWR | O_CLOEXEC);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(openat(0, "filename", O_RDWR | O_CLOEXEC));
+  // CHECK-MESSAGES-NOT: warning:
+  openat(0, "filename", O_RDWR | O_CLOEXEC | O_EXCL);
+  // CHECK-MESSAGES-NOT: warning:
+  TEMP_FAILURE_RETRY(openat(0, "filename", O_RDWR | O_CLOEXEC | O_EXCL));
+  // CHECK-MESSAGES-NOT: warning:
+}
+
+class G {
+public:
+  int open(const char *pathname, int flags, ...);
+  int open64(const char *pathname, int flags, ...);
+  int openat(int dirfd, const char *pathname, int flags, ...);
+
+  void h() {
+    open("filename", O_RDWR);
+    // CHECK-MESSAGES-NOT: warning:
+    TEMP_FAILURE_RETRY(open("filename", O_RDWR));
+    // CHECK-MESSAGES-NOT: warning:
+    open64("filename", O_RDWR);
+    // CHECK-MESSAGES-NOT: warning:
+    TEMP_FAILURE_RETRY(open64("filename", O_RDWR));
+    // CHECK-MESSAGES-NOT: warning:
+    openat(0, "filename", O_RDWR);
+    // CHECK-MESSAGES-NOT: warning:
+    TEMP_FAILURE_RETRY(openat(0, "filename", O_RDWR));
+    // CHECK-MESSAGES-NOT: warning:
+  }
+};
diff --git a/test/clang-tidy/android-cloexec-socket.cpp b/test/clang-tidy/android-cloexec-socket.cpp
new file mode 100644
index 0000000..25f332d
--- /dev/null
+++ b/test/clang-tidy/android-cloexec-socket.cpp
@@ -0,0 +1,75 @@
+// RUN: %check_clang_tidy %s android-cloexec-socket %t
+
+#define SOCK_STREAM 1
+#define SOCK_DGRAM 2
+#define __O_CLOEXEC 3
+#define SOCK_CLOEXEC __O_CLOEXEC
+#define TEMP_FAILURE_RETRY(exp) \
+  ({                            \
+    int _rc;                    \
+    do {                        \
+      _rc = (exp);              \
+    } while (_rc == -1);        \
+  })
+
+extern "C" int socket(int domain, int type, int protocol);
+
+void a() {
+  socket(0, SOCK_STREAM, 0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: 'socket' should use SOCK_CLOEXEC where possible [android-cloexec-socket]
+  // CHECK-FIXES: socket(0, SOCK_STREAM | SOCK_CLOEXEC, 0)
+  TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM, 0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: 'socket'
+  // CHECK-FIXES: TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM | SOCK_CLOEXEC, 0))
+  socket(0, SOCK_STREAM | SOCK_DGRAM, 0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: 'socket'
+  // CHECK-FIXES: socket(0, SOCK_STREAM | SOCK_DGRAM | SOCK_CLOEXEC, 0)
+  TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM | SOCK_DGRAM, 0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:56: warning: 'socket'
+  // CHECK-FIXES: TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM | SOCK_DGRAM | SOCK_CLOEXEC, 0))
+}
+
+void f() {
+  socket(0, 3, 0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: 'socket'
+  // CHECK-FIXES: socket(0, 3 | SOCK_CLOEXEC, 0)
+  TEMP_FAILURE_RETRY(socket(0, 3, 0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: 'socket'
+  // CHECK-FIXES: TEMP_FAILURE_RETRY(socket(0, 3 | SOCK_CLOEXEC, 0))
+
+  int flag = 3;
+  socket(0, flag, 0);
+  TEMP_FAILURE_RETRY(socket(0, flag, 0));
+}
+
+namespace i {
+int socket(int domain, int type, int protocol);
+
+void d() {
+  socket(0, SOCK_STREAM, 0);
+  TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM, 0));
+  socket(0, SOCK_STREAM | SOCK_DGRAM, 0);
+  TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM | SOCK_DGRAM, 0));
+}
+
+} // namespace i
+
+void e() {
+  socket(0, SOCK_CLOEXEC, 0);
+  TEMP_FAILURE_RETRY(socket(0, SOCK_CLOEXEC, 0));
+  socket(0, SOCK_STREAM | SOCK_CLOEXEC, 0);
+  TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM | SOCK_CLOEXEC, 0));
+  socket(0, SOCK_STREAM | SOCK_CLOEXEC | SOCK_DGRAM, 0);
+  TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM | SOCK_CLOEXEC | SOCK_DGRAM, 0));
+}
+
+class G {
+public:
+  int socket(int domain, int type, int protocol);
+  void d() {
+    socket(0, SOCK_STREAM, 0);
+    TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM, 0));
+    socket(0, SOCK_STREAM | SOCK_DGRAM, 0);
+    TEMP_FAILURE_RETRY(socket(0, SOCK_STREAM | SOCK_DGRAM, 0));
+  }
+};
diff --git a/test/clang-tidy/bugprone-integer-division.cpp b/test/clang-tidy/bugprone-integer-division.cpp
new file mode 100644
index 0000000..243ad46
--- /dev/null
+++ b/test/clang-tidy/bugprone-integer-division.cpp
@@ -0,0 +1,130 @@
+// RUN: %check_clang_tidy %s bugprone-integer-division %t
+
+// Functions expecting a floating-point parameter.
+void floatArg(float x) {}
+void doubleArg(double x) {}
+void longDoubleArg(long double x) {}
+
+// Functions expected to return a floating-point value.
+float singleDiv() {
+  int x = -5;
+  int y = 2;
+  return x/y;
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: result of integer division used in
+}
+
+double wrongOrder(int x, int y) {
+  return x/y/0.1;
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: result of integer division used in
+}
+
+long double rightOrder(int x, int y) {
+  return 0.1/x/y; // OK
+}
+
+// Typical mathematical functions.
+float sin(float);
+double acos(double);
+long double tanh(long double);
+
+namespace std {
+  using ::sin;
+}
+
+template <typename T>
+void intDivSin(T x) {
+  sin(x);
+}
+
+int intFunc(int);
+
+struct X {
+  int n;
+  void m() {
+    sin(n / 3);
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: result of integer division used in
+  }
+};
+
+void integerDivision() {
+  char a = 2;
+  short b = -5;
+  int c = 9784;
+  enum third { x, y, z=2 };
+  third d = z;
+  char e[] = {'a', 'b', 'c'};
+  char f = *(e + 1 / a);
+  bool g = 1;
+
+  sin(1 + c / (2 + 2));
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: result of integer division used in
+  sin(c / (1 + .5));
+  sin((c + .5) / 3);
+
+  sin(intFunc(3) / 5);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: result of integer division used in
+  acos(2 / intFunc(7));
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: result of integer division used in
+
+  floatArg(1 + 2 / 3);
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: result of integer division used in
+  sin(1 + 2 / 3);
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: result of integer division used in
+  intFunc(sin(1 + 2 / 3));
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: result of integer division used in
+
+  floatArg(1 + intFunc(1 + 2 / 3));
+  floatArg(1 + 3 * intFunc(a / b));
+
+  1 << (2 / 3);
+  1 << intFunc(2 / 3);
+
+#define M_SIN sin(a / b);
+  M_SIN
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: result of integer division used in
+
+  intDivSin<float>(a / b);
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: result of integer division used in
+  intDivSin<double>(c / d);
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: result of integer division used in
+  intDivSin<long double>(f / g);
+// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: result of integer division used in
+
+  floatArg(1 / 3);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: result of integer division used in
+  doubleArg(a / b);
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: result of integer division used in
+  longDoubleArg(3 / d);
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: result of integer division used in
+  floatArg(a / b / 0.1);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: result of integer division used in
+  doubleArg(1 / 3 / 0.1);
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: result of integer division used in
+  longDoubleArg(2 / 3 / 5);
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: result of integer division used in
+
+  std::sin(2 / 3);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: result of integer division used in
+  ::acos(7 / d);
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: result of integer division used in
+  tanh(f / g);
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: result of integer division used in
+
+  floatArg(0.1 / a / b);
+  doubleArg(0.1 / 3 / 1);
+
+  singleDiv();
+  wrongOrder(a,b);
+  rightOrder(a,b);
+
+  sin(a / b);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: result of integer division used in
+  acos(f / d);
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: result of integer division used in
+  tanh(c / g);
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: result of integer division used in
+
+  sin(3.0 / a);
+  acos(b / 3.14);
+  tanh(3.14 / f / g);
+}
diff --git a/test/clang-tidy/bugprone-suspicious-memset-usage.cpp b/test/clang-tidy/bugprone-suspicious-memset-usage.cpp
new file mode 100644
index 0000000..f33ae5a
--- /dev/null
+++ b/test/clang-tidy/bugprone-suspicious-memset-usage.cpp
@@ -0,0 +1,77 @@
+// RUN: %check_clang_tidy %s bugprone-suspicious-memset-usage %t
+
+void *memset(void *, int, __SIZE_TYPE__);
+
+namespace std {
+  using ::memset;
+}
+
+template <typename T>
+void mtempl(int *ptr) {
+  memset(ptr, '0', sizeof(T));
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: memset fill value is char '0', potentially mistaken for int 0 [bugprone-suspicious-memset-usage]
+// CHECK-FIXES: memset(ptr, 0, sizeof(T));
+  memset(ptr, 256, sizeof(T));
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: memset fill value is out of unsigned character range, gets truncated [bugprone-suspicious-memset-usage]
+  memset(0, sizeof(T), 0);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]
+// CHECK-FIXES: memset(0, 0, sizeof(T));
+  memset(0, sizeof(int), 0);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]
+// CHECK-FIXES: memset(0, 0, sizeof(int));
+}
+
+void foo(int xsize, int ysize) {
+  int i[5] = {1, 2, 3, 4, 5};
+  char ca[3] = {'a', 'b', 'c'};
+  int *p = i;
+  int l = 5;
+  char z = '1';
+  char *c = &z;
+  int v = 0;
+
+  memset(p, '0', l);
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: memset fill value is char '0', potentially mistaken for int 0 [bugprone-suspicious-memset-usage]
+// CHECK-FIXES: memset(p, 0, l);
+
+  memset(p, 0xabcd, l);
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: memset fill value is out of unsigned character range, gets truncated [bugprone-suspicious-memset-usage]
+
+  memset(p, sizeof(int), 0);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]
+// CHECK-FIXES: memset(p, 0, sizeof(int));
+  std::memset(p, sizeof(int), 0x00);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]
+// CHECK-FIXES: std::memset(p, 0x00, sizeof(int));
+
+#define M_CHAR_ZERO memset(p, '0', l);
+  M_CHAR_ZERO
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset fill value is char '0', potentially mistaken for int 0 [bugprone-suspicious-memset-usage]
+
+#define M_OUTSIDE_RANGE memset(p, 0xabcd, l);
+  M_OUTSIDE_RANGE
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset fill value is out of unsigned character range, gets truncated [bugprone-suspicious-memset-usage]
+
+#define M_ZERO_LENGTH memset(p, sizeof(int), 0);
+  M_ZERO_LENGTH
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]
+
+  memset(p, '2', l);
+  memset(p, 0, l);
+  memset(c, '0', 1);
+  memset(ca, '0', sizeof(ca));
+
+  memset(p, 0x00, l);
+  mtempl<int>(p);
+
+  memset(p, sizeof(int), v + 1);
+  memset(p, 0xcd, 1);
+
+  // Don't warn when the fill char and the length are both known to be
+  // zero.  No bug is possible.
+  memset(p, 0, v);
+
+  // -1 is clearly not a length by virtue of being negative, so no warning
+  // despite v == 0.
+  memset(p, -1, v);
+}
diff --git a/test/clang-tidy/bugprone-undefined-memory-manipulation.cpp b/test/clang-tidy/bugprone-undefined-memory-manipulation.cpp
new file mode 100644
index 0000000..8055010
--- /dev/null
+++ b/test/clang-tidy/bugprone-undefined-memory-manipulation.cpp
@@ -0,0 +1,213 @@
+// RUN: %check_clang_tidy %s bugprone-undefined-memory-manipulation %t
+
+void *memset(void *, int, __SIZE_TYPE__);
+void *memcpy(void *, const void *, __SIZE_TYPE__);
+void *memmove(void *, const void *, __SIZE_TYPE__);
+
+namespace std {
+using ::memcpy;
+using ::memmove;
+using ::memset;
+}
+
+namespace types {
+// TriviallyCopyable types:
+struct Plain {
+  int n;
+};
+
+enum E {
+  X,
+  Y,
+  Z
+};
+
+struct Base {
+  float b;
+};
+
+struct Derived : Base {
+  bool d;
+};
+
+// not TriviallyCopyable types:
+struct Destruct {
+  ~Destruct() {}
+};
+
+struct Copy {
+  Copy() {}
+  Copy(const Copy &) {}
+};
+
+struct Move {
+  Move() {}
+  Move(Move &&) {}
+};
+
+struct VirtualFunc {
+  virtual void f() {}
+};
+
+struct VirtualBase : virtual Base {
+  int vb;
+};
+
+// Incomplete type, assume it is TriviallyCopyable.
+struct NoDef;
+
+} // end namespace types
+
+void f(types::NoDef *s) {
+  memset(s, 0, 5);
+}
+
+template <typename T>
+void memset_temp(T *b) {
+  memset(b, 0, sizeof(T));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualFunc' is not TriviallyCopyable [bugprone-undefined-memory-manipulation]
+}
+
+template <typename S, typename T>
+void memcpy_temp(S *a, T *b) {
+  memcpy(a, b, sizeof(T));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::VirtualFunc'
+}
+
+template <typename S, typename T>
+void memmove_temp(S *a, T *b) {
+  memmove(a, b, sizeof(T));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::VirtualFunc'
+}
+
+namespace aliases {
+using Copy2 = types::Copy;
+typedef types::Move Move2;
+}
+
+void notTriviallyCopyable() {
+  types::Plain p; // TriviallyCopyable for variety
+  types::Destruct d;
+  types::Copy c;
+  types::Move m;
+  types::VirtualFunc vf;
+  types::VirtualBase vb;
+
+  memset(&vf, 0, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualFunc'
+  memset(&d, 0, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Destruct'
+  memset(&c, 0, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Copy'
+  std::memset(&m, 0, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Move'
+  ::memset(&vb, 0, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualBase'
+
+  memcpy(&p, &vf, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::VirtualFunc'
+  memcpy(&p, &d, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::Destruct'
+  memcpy(&c, &p, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Copy'
+  std::memcpy(&m, &p, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Move'
+  ::memcpy(&vb, &p, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualBase'
+
+  memmove(&vf, &p, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualFunc'
+  memmove(&d, &p, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Destruct'
+  memmove(&p, &c, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::Copy'
+  std::memmove(&p, &m, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::Move'
+  ::memmove(&p, &vb, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::VirtualBase'
+
+#define MEMSET memset(&vf, 0, sizeof(int));
+  MEMSET
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualFunc'
+#define MEMCPY memcpy(&d, &p, sizeof(int));
+  MEMCPY
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Destruct'
+#define MEMMOVE memmove(&p, &c, sizeof(int));
+  MEMMOVE
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::Copy'
+
+  memset_temp<types::VirtualFunc>(&vf);
+  memcpy_temp<types::Plain, types::VirtualFunc>(&p, &vf);
+  memmove_temp<types::Plain, types::VirtualFunc>(&p, &vf);
+
+  aliases::Copy2 c2;
+  aliases::Move2 m2;
+  memset(&c2, 0, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'aliases::Copy2'
+  memset(&m2, 0, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'aliases::Move2'
+
+  typedef aliases::Copy2 Copy3;
+  typedef aliases::Copy2 *PCopy2;
+  typedef Copy3 *PCopy3;
+  Copy3 c3;
+  PCopy2 pc2;
+  PCopy3 pc3;
+  memset(&c3, 0, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'Copy3'
+  memset(pc2, 0, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'aliases::Copy2'
+  memset(pc3, 0, sizeof(int));
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'Copy3'
+}
+
+void triviallyCopyable() {
+  types::Plain p;
+  types::Base base;
+  types::Derived derived;
+
+  int i = 5;
+  int ia[3] = {1, 2, 3};
+  float f = 3.14;
+  float fa[3] = {1.1, 2.2, 3.3};
+  bool b = false;
+  bool ba[2] = {true, false};
+  types::E e = types::X;
+  p.n = 2;
+
+  memset(&p, 0, sizeof(int));
+  memset(&base, 0, sizeof(float));
+  memset(&derived, 0, sizeof(bool));
+  memset(&i, 0, sizeof(int));
+  memset(ia, 0, sizeof(int));
+  memset(&f, 0, sizeof(float));
+  memset(fa, 0, sizeof(float));
+  memset(&b, 0, sizeof(bool));
+  memset(ba, 0, sizeof(bool));
+  memset(&e, 0, sizeof(int));
+  memset(&p.n, 0, sizeof(int));
+
+  memcpy(&p, &p, sizeof(int));
+  memcpy(&base, &base, sizeof(float));
+  memcpy(&derived, &derived, sizeof(bool));
+  memcpy(&i, &i, sizeof(int));
+  memcpy(ia, ia, sizeof(int));
+  memcpy(&f, &f, sizeof(float));
+  memcpy(fa, fa, sizeof(float));
+  memcpy(&b, &b, sizeof(bool));
+  memcpy(ba, ba, sizeof(bool));
+  memcpy(&e, &e, sizeof(int));
+  memcpy(&p.n, &p.n, sizeof(int));
+
+  memmove(&p, &p, sizeof(int));
+  memmove(&base, &base, sizeof(float));
+  memmove(&derived, &derived, sizeof(bool));
+  memmove(&i, &i, sizeof(int));
+  memmove(ia, ia, sizeof(int));
+  memmove(&f, &f, sizeof(float));
+  memmove(fa, fa, sizeof(float));
+  memmove(&b, &b, sizeof(bool));
+  memmove(ba, ba, sizeof(bool));
+  memmove(&e, &e, sizeof(int));
+  memmove(&p.n, &p.n, sizeof(int));
+}
diff --git a/test/clang-tidy/check_clang_tidy.py b/test/clang-tidy/check_clang_tidy.py
index c950042..1ade4cd 100755
--- a/test/clang-tidy/check_clang_tidy.py
+++ b/test/clang-tidy/check_clang_tidy.py
@@ -17,6 +17,7 @@
 
 Usage:
   check_clang_tidy.py [-resource-dir <resource-dir>] \
+    [-assume-filename <file-with-source-extension>] \
     <source-file> <check-name> <temp-file> \
     -- [optional clang-tidy arguments]
 
@@ -25,6 +26,7 @@
 """
 
 import argparse
+import os
 import re
 import subprocess
 import sys
@@ -38,6 +40,7 @@
 def main():
   parser = argparse.ArgumentParser()
   parser.add_argument('-resource-dir')
+  parser.add_argument('-assume-filename')
   parser.add_argument('input_file_name')
   parser.add_argument('check_name')
   parser.add_argument('temp_file_name')
@@ -45,21 +48,25 @@
   args, extra_args = parser.parse_known_args()
 
   resource_dir = args.resource_dir
+  assume_file_name = args.assume_filename
   input_file_name = args.input_file_name
   check_name = args.check_name
   temp_file_name = args.temp_file_name
 
-  extension = '.cpp'
-  if (input_file_name.endswith('.c')):
-    extension = '.c'
-  if (input_file_name.endswith('.hpp')):
-    extension = '.hpp'
+  file_name_with_extension = assume_file_name or input_file_name
+  _, extension = os.path.splitext(file_name_with_extension)
+  if extension not in ['.c', '.hpp', '.m', '.mm']:
+    extension = '.cpp'
   temp_file_name = temp_file_name + extension
 
   clang_tidy_extra_args = extra_args
   if len(clang_tidy_extra_args) == 0:
-    clang_tidy_extra_args = ['--', '--std=c++11'] if extension == '.cpp' \
-                       else ['--']
+    clang_tidy_extra_args = ['--']
+    if extension in ['.cpp', '.hpp', '.mm']:
+      clang_tidy_extra_args.append('--std=c++11')
+    if extension in ['.m', '.mm']:
+      clang_tidy_extra_args.extend(
+          ['-fobjc-abi-version=2', '-fobjc-arc'])
 
   # Tests should not rely on STL being available, and instead provide mock
   # implementations of relevant APIs.
diff --git a/test/clang-tidy/cppcoreguidelines-owning-memory-containers.cpp b/test/clang-tidy/cppcoreguidelines-owning-memory-containers.cpp
new file mode 100644
index 0000000..929b33d
--- /dev/null
+++ b/test/clang-tidy/cppcoreguidelines-owning-memory-containers.cpp
@@ -0,0 +1,61 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-owning-memory %t
+
+namespace gsl {
+template <typename T>
+using owner = T;
+}
+
+namespace std {
+
+// Not actually a vector, but more a dynamic, fixed size array. Just to demonstrate
+// functionality or the lack of the same.
+template <typename T>
+class vector {
+public:
+  vector(unsigned long size, T val) : data{new T[size]}, size{size} {
+    for (unsigned long i = 0ul; i < size; ++i) {
+      data[i] = val;
+    }
+  }
+
+  T *begin() { return data; }
+  T *end() { return &data[size]; }
+  T &operator[](unsigned long index) { return data[index]; }
+
+private:
+  T *data;
+  unsigned long size;
+};
+
+} // namespace std
+
+// All of the following codesnippets should be valid with appropriate 'owner<>' anaylsis,
+// but currently the type information of 'gsl::owner<>' gets lost in typededuction.
+int main() {
+  std::vector<gsl::owner<int *>> OwnerStdVector(100, nullptr);
+
+  // Rangebased looping in resource vector.
+  for (auto *Element : OwnerStdVector) {
+    Element = new int(42);
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: assigning newly created 'gsl::owner<>' to non-owner 'int *'
+  }
+  for (auto *Element : OwnerStdVector) {
+    delete Element;
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: deleting a pointer through a type that is not marked 'gsl::owner<>'; consider using a smart pointer instead
+    // CHECK-MESSAGES: [[@LINE-3]]:8: note: variable declared here
+  }
+
+  // Indexbased looping in resource vector.
+  for (int i = 0; i < 100; ++i) {
+    OwnerStdVector[i] = new int(42);
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: assigning newly created 'gsl::owner<>' to non-owner 'int *'
+  }
+  for (int i = 0; i < 100; ++i) {
+    delete OwnerStdVector[i];
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: deleting a pointer through a type that is not marked 'gsl::owner<>'; consider using a smart pointer instead
+    // A note gets emitted here pointing to the return value of the operator[] from the
+    // vector implementation. Maybe this is considered misleading.
+  }
+
+  return 0;
+}
diff --git a/test/clang-tidy/cppcoreguidelines-owning-memory-legacy-functions.cpp b/test/clang-tidy/cppcoreguidelines-owning-memory-legacy-functions.cpp
new file mode 100644
index 0000000..5785e9f
--- /dev/null
+++ b/test/clang-tidy/cppcoreguidelines-owning-memory-legacy-functions.cpp
@@ -0,0 +1,194 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-owning-memory %t \
+// RUN: -config='{CheckOptions: \
+// RUN:  [{key: cppcoreguidelines-owning-memory.LegacyResourceProducers, value: "::malloc;::aligned_alloc;::realloc;::calloc;::fopen;::freopen;::tmpfile"}, \
+// RUN:   {key: cppcoreguidelines-owning-memory.LegacyResourceConsumers, value: "::free;::realloc;::freopen;::fclose"}]}' \
+// RUN: -- -std=c++11 -nostdlib -nostdinc++
+
+namespace gsl {
+template <class T>
+using owner = T;
+} // namespace gsl
+
+extern "C" {
+using size_t = decltype(sizeof(void*));
+using FILE = int;
+
+void *malloc(size_t ByteCount);
+void *aligned_alloc(size_t Alignment, size_t Size);
+void *calloc(size_t Count, size_t SizeSingle);
+void *realloc(void *Resource, size_t NewByteCount);
+void free(void *Resource);
+
+FILE *tmpfile(void);
+FILE *fopen(const char *filename, const char *mode);
+FILE *freopen(const char *filename, const char *mode, FILE *stream);
+void fclose(FILE *Resource);
+}
+
+namespace std {
+using ::FILE;
+using ::size_t;
+
+using ::fclose;
+using ::fopen;
+using ::freopen;
+using ::tmpfile;
+
+using ::aligned_alloc;
+using ::calloc;
+using ::free;
+using ::malloc;
+using ::realloc;
+} // namespace std
+
+void nonOwningCall(int *Resource, size_t Size) {}
+void nonOwningCall(FILE *Resource) {}
+
+void consumesResource(gsl::owner<int *> Resource, size_t Size) {}
+void consumesResource(gsl::owner<FILE *> Resource) {}
+
+void testNonCasted(void *Resource) {}
+
+void testNonCastedOwner(gsl::owner<void *> Resource) {}
+
+FILE *fileFactory1() { return ::fopen("new_file.txt", "w"); }
+// CHECK-MESSAGES: [[@LINE-1]]:24: warning: returning a newly created resource of type 'FILE *' (aka 'int *') or 'gsl::owner<>' from a function whose return type is not 'gsl::owner<>'
+gsl::owner<FILE *> fileFactory2() { return std::fopen("new_file.txt", "w"); } // Ok
+
+int *arrayFactory1() { return (int *)std::malloc(100); }
+// CHECK-MESSAGES: [[@LINE-1]]:24: warning: returning a newly created resource of type 'int *' or 'gsl::owner<>' from a function whose return type is not 'gsl::owner<>'
+gsl::owner<int *> arrayFactory2() { return (int *)std::malloc(100); } // Ok
+void *dataFactory1() { return std::malloc(100); }
+// CHECK-MESSAGES: [[@LINE-1]]:24: warning: returning a newly created resource of type 'void *' or 'gsl::owner<>' from a function whose return type is not 'gsl::owner<>'
+gsl::owner<void *> dataFactory2() { return std::malloc(100); } // Ok
+
+void test_resource_creators() {
+  const unsigned int ByteCount = 25 * sizeof(int);
+  int Bad = 42;
+
+  int *IntArray1 = (int *)std::malloc(ByteCount);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+  int *IntArray2 = static_cast<int *>(std::malloc(ByteCount)); // Bad
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+  void *IntArray3 = std::malloc(ByteCount);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'void *' with a newly created 'gsl::owner<>'
+
+  int *IntArray4 = (int *)::malloc(ByteCount);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+  int *IntArray5 = static_cast<int *>(::malloc(ByteCount)); // Bad
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+  void *IntArray6 = ::malloc(ByteCount);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'void *' with a newly created 'gsl::owner<>'
+
+  gsl::owner<int *> IntArray7 = (int *)malloc(ByteCount); // Ok
+  gsl::owner<void *> IntArray8 = malloc(ByteCount);       // Ok
+
+  gsl::owner<int *> IntArray9 = &Bad;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'int *'
+
+  nonOwningCall((int *)malloc(ByteCount), 25);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: initializing non-owner argument of type 'int *' with a newly created 'gsl::owner<>'
+  nonOwningCall((int *)::malloc(ByteCount), 25);
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: initializing non-owner argument of type 'int *' with a newly created 'gsl::owner<>'
+
+  consumesResource((int *)malloc(ByteCount), 25);   // Ok
+  consumesResource((int *)::malloc(ByteCount), 25); // Ok
+
+  testNonCasted(malloc(ByteCount));
+  // CHECK-MESSAGES: [[@LINE-1]]:17: warning: initializing non-owner argument of type 'void *' with a newly created 'gsl::owner<>'
+  testNonCastedOwner(gsl::owner<void *>(malloc(ByteCount))); // Ok
+  testNonCastedOwner(malloc(ByteCount));                     // Ok
+
+  FILE *File1 = std::fopen("test_name.txt", "w+");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+  FILE *File2 = ::fopen("test_name.txt", "w+");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+
+  gsl::owner<FILE *> File3 = ::fopen("test_name.txt", "w+"); // Ok
+
+  FILE *File4;
+  File4 = ::fopen("test_name.txt", "w+");
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: assigning newly created 'gsl::owner<>' to non-owner 'FILE *' (aka 'int *')
+
+  gsl::owner<FILE *> File5;
+  File5 = ::fopen("test_name.txt", "w+"); // Ok
+  File5 = File1;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected assignment source to be of type 'gsl::owner<>'; got 'FILE *' (aka 'int *')
+
+  gsl::owner<FILE *> File6 = File1;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'FILE *' (aka 'int *')
+
+  FILE *File7 = tmpfile();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+  gsl::owner<FILE *> File8 = tmpfile(); // Ok
+
+  nonOwningCall(::fopen("test_name.txt", "r"));
+  // CHECK-MESSAGES: [[@LINE-1]]:17: warning: initializing non-owner argument of type 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+  nonOwningCall(std::fopen("test_name.txt", "r"));
+  // CHECK-MESSAGES: [[@LINE-1]]:17: warning: initializing non-owner argument of type 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+
+  consumesResource(::fopen("test_name.txt", "r")); // Ok
+
+  int *HeapPointer3 = (int *)aligned_alloc(16ul, 4ul * 32ul);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+  gsl::owner<int *> HeapPointer4 = static_cast<int *>(aligned_alloc(16ul, 4ul * 32ul)); // Ok
+
+  void *HeapPointer5 = calloc(10ul, 4ul);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'void *' with a newly created 'gsl::owner<>'
+  gsl::owner<void *> HeapPointer6 = calloc(10ul, 4ul); // Ok
+}
+
+void test_legacy_consumers() {
+  int StackInteger = 42;
+
+  int *StackPointer = &StackInteger;
+  int *HeapPointer1 = (int *)malloc(100);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+  gsl::owner<int *> HeapPointer2 = (int *)malloc(100);
+
+  std::free(StackPointer);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling legacy resource function without passing a 'gsl::owner<>'
+  std::free(HeapPointer1);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling legacy resource function without passing a 'gsl::owner<>'
+  std::free(HeapPointer2); // Ok
+  // CHECK MESSAGES: [[@LINE-1]]:3: warning: calling legacy resource function without passing a 'gsl::owner<>'
+
+  // FIXME: the check complains about initialization of 'void *' with new created owner.
+  // This happens, because the argument of `free` is not marked as 'owner<>' (and cannot be),
+  // and the check will not figure out could be meant as owner.
+  // This property will probably never be fixed, because it is probably a rather rare
+  // use-case and 'owner<>' should be wrapped in RAII classes anyway!
+  std::free(std::malloc(100)); // Ok but silly :)
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: initializing non-owner argument of type 'void *' with a newly created 'gsl::owner<>'
+
+  // Demonstrate, that multi-argument functions are diagnosed as well.
+  std::realloc(StackPointer, 200);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling legacy resource function without passing a 'gsl::owner<>'
+  std::realloc(HeapPointer1, 200);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling legacy resource function without passing a 'gsl::owner<>'
+  std::realloc(HeapPointer2, 200);     // Ok
+  std::realloc(std::malloc(100), 200); // Ok but silly
+  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: initializing non-owner argument of type 'void *' with a newly created 'gsl::owner<>'
+
+  fclose(fileFactory1());
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: calling legacy resource function without passing a 'gsl::owner<>'
+  fclose(fileFactory2()); // Ok, same as FIXME with `free(malloc(100))` applies here
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: initializing non-owner argument of type 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+
+  gsl::owner<FILE *> File1 = fopen("testfile.txt", "r"); // Ok
+  FILE *File2 = freopen("testfile.txt", "w", File1);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+  // CHECK-MESSAGES: [[@LINE-2]]:17: warning: calling legacy resource function without passing a 'gsl::owner<>'
+  // FIXME: The warning for not passing and owner<> is a false positive since both the filename and the
+  // mode are not supposed to be owners but still pointers. The check is to coarse for
+  // this function. Maybe `freopen` gets special treatment.
+
+  gsl::owner<FILE *> File3 = freopen("testfile.txt", "w", File2); // Bad, File2 no owner
+  // CHECK-MESSAGES: [[@LINE-1]]:30: warning: calling legacy resource function without passing a 'gsl::owner<>'
+
+  FILE *TmpFile = tmpfile();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+  FILE *File6 = freopen("testfile.txt", "w", TmpFile); // Bad, both return and argument
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'FILE *' (aka 'int *') with a newly created 'gsl::owner<>'
+  // CHECK-MESSAGES: [[@LINE-2]]:17: warning: calling legacy resource function without passing a 'gsl::owner<>'
+}
diff --git a/test/clang-tidy/cppcoreguidelines-owning-memory.cpp b/test/clang-tidy/cppcoreguidelines-owning-memory.cpp
new file mode 100644
index 0000000..967c086
--- /dev/null
+++ b/test/clang-tidy/cppcoreguidelines-owning-memory.cpp
@@ -0,0 +1,391 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-owning-memory %t
+
+namespace gsl {
+template <class T>
+using owner = T;
+} // namespace gsl
+
+template <typename T>
+class unique_ptr {
+public:
+  unique_ptr(gsl::owner<T> resource) : memory(resource) {}
+  unique_ptr(const unique_ptr<T> &) = default;
+
+  ~unique_ptr() { delete memory; }
+
+private:
+  gsl::owner<T> memory;
+};
+
+void takes_owner(gsl::owner<int *> owned_int) {
+}
+
+void takes_pointer(int *unowned_int) {
+}
+
+void takes_owner_and_more(int some_int, gsl::owner<int *> owned_int, float f) {
+}
+
+template <typename T>
+void takes_templated_owner(gsl::owner<T> owned_T) {
+}
+
+gsl::owner<int *> returns_owner1() { return gsl::owner<int *>(new int(42)); } // Ok
+gsl::owner<int *> returns_owner2() { return new int(42); }                    // Ok
+
+int *returns_no_owner1() { return nullptr; }
+int *returns_no_owner2() {
+  return new int(42);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: returning a newly created resource of type 'int *' or 'gsl::owner<>' from a function whose return type is not 'gsl::owner<>'
+}
+int *returns_no_owner3() {
+  int *should_be_owner = new int(42);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+  return should_be_owner;
+}
+int *returns_no_owner4() {
+  gsl::owner<int *> owner = new int(42);
+  return owner;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: returning a newly created resource of type 'int *' or 'gsl::owner<>' from a function whose return type is not 'gsl::owner<>'
+}
+
+unique_ptr<int *> returns_no_owner5() {
+  return unique_ptr<int *>(new int(42)); // Ok
+}
+
+/// FIXME: CSA finds it, but the report is misleading. Ownersemantics can catch this
+/// by flow analysis similar to misc-use-after-move.
+void csa_not_finding_leak() {
+  gsl::owner<int *> o1 = new int(42); // Ok
+
+  gsl::owner<int *> o2 = o1; // Ok
+  o2 = new int(45);          // conceptual leak, the memory from o1 is now leaked, since its considered moved in the guidelines
+
+  delete o2;
+  // actual leak occurs here, its found, but mixed
+  delete o1;
+}
+
+void test_assignment_and_initialization() {
+  int stack_int1 = 15;
+  int stack_int2;
+
+  gsl::owner<int *> owned_int1 = &stack_int1; // BAD
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'int *'
+
+  gsl::owner<int *> owned_int2;
+  owned_int2 = &stack_int2; // BAD since no owner, bad since uninitialized
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected assignment source to be of type 'gsl::owner<>'; got 'int *'
+
+  gsl::owner<int *> owned_int3 = new int(42); // Good
+  owned_int3 = nullptr;                       // Good
+
+  gsl::owner<int *> owned_int4(nullptr); // Ok
+  owned_int4 = new int(42);              // Good
+
+  gsl::owner<int *> owned_int5 = owned_int3; // Good
+
+  gsl::owner<int *> owned_int6{nullptr}; // Ok
+  owned_int6 = owned_int4;               // Good
+
+  // FIXME:, flow analysis for the case of reassignment. Value must be released before
+  owned_int6 = owned_int3; // BAD, because reassignment without resource release
+
+  auto owned_int7 = returns_owner1(); // Bad, since type deduction eliminates the owner wrapper
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+  // CHECK-MESSAGES: [[@LINE-2]]:3: note: type deduction did not result in an owner
+
+  const auto owned_int8 = returns_owner2(); // Bad, since type deduction eliminates the owner wrapper
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *const' with a newly created 'gsl::owner<>'
+  // CHECK-MESSAGES: [[@LINE-2]]:3: note: type deduction did not result in an owner
+
+  gsl::owner<int *> owned_int9 = returns_owner1(); // Ok
+  int *unowned_int3 = returns_owner1();            // Bad
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+
+  gsl::owner<int *> owned_int10;
+  owned_int10 = returns_owner1(); // Ok
+
+  int *unowned_int4;
+  unowned_int4 = returns_owner1(); // Bad
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: assigning newly created 'gsl::owner<>' to non-owner 'int *'
+
+  gsl::owner<int *> owned_int11 = returns_no_owner1(); // Bad since no owner
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'int *'
+
+  gsl::owner<int *> owned_int12;
+  owned_int12 = returns_no_owner1(); // Bad since no owner
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected assignment source to be of type 'gsl::owner<>'; got 'int *'
+
+  int *unowned_int5 = returns_no_owner1(); // Ok
+  int *unowned_int6;
+  unowned_int6 = returns_no_owner1(); // Ok
+
+  int *unowned_int7 = new int(42); // Bad, since resource not assigned to an owner
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+
+  int *unowned_int8;
+  unowned_int8 = new int(42);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: assigning newly created 'gsl::owner<>' to non-owner 'int *'
+
+  gsl::owner<int *> owned_int13 = nullptr; // Ok
+}
+
+void test_deletion() {
+  gsl::owner<int *> owned_int1 = new int(42);
+  delete owned_int1; // Good
+
+  gsl::owner<int *> owned_int2 = new int[42];
+  delete[] owned_int2; // Good
+
+  int *unowned_int1 = new int(42); // BAD, since new creates and owner
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+  delete unowned_int1; // BAD, since no owner
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: deleting a pointer through a type that is not marked 'gsl::owner<>'; consider using a smart pointer instead
+  // CHECK-MESSAGES: [[@LINE-4]]:3: note: variable declared here
+
+  int *unowned_int2 = new int[42]; // BAD, since new creates and owner
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
+  delete[] unowned_int2; // BAD since no owner
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: deleting a pointer through a type that is not marked 'gsl::owner<>'; consider using a smart pointer instead
+  // CHECK-MESSAGES: [[@LINE-4]]:3: note: variable declared here
+
+  delete new int(42);   // Technically ok, but stupid
+  delete[] new int[42]; // Technically ok, but stupid
+}
+
+void test_owner_function_calls() {
+  int stack_int = 42;
+  int *unowned_int1 = &stack_int;
+  takes_owner(&stack_int); // BAD
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: expected argument of type 'gsl::owner<>'; got 'int *'
+  takes_owner(unowned_int1); // BAD
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: expected argument of type 'gsl::owner<>'; got 'int *'
+
+  gsl::owner<int *> owned_int1 = new int(42);
+  takes_owner(owned_int1); // Ok
+
+  takes_owner_and_more(42, &stack_int, 42.0f); // BAD
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: expected argument of type 'gsl::owner<>'; got 'int *'
+  takes_owner_and_more(42, unowned_int1, 42.0f); // BAD
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: expected argument of type 'gsl::owner<>'; got 'int *'
+
+  takes_owner_and_more(42, new int(42), 42.0f); // Ok, since new is consumed by owner
+  takes_owner_and_more(42, owned_int1, 42.0f);  // Ok, since owner as argument
+
+  takes_templated_owner(owned_int1);   // Ok
+  takes_templated_owner(new int(42));  // Ok
+  takes_templated_owner(unowned_int1); // Bad
+  // CHECK-MESSAGES: [[@LINE-1]]:25: warning: expected argument of type 'gsl::owner<>'; got 'int *'
+
+  takes_owner(returns_owner1());    // Ok
+  takes_owner(returns_no_owner1()); // BAD
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: expected argument of type 'gsl::owner<>'; got 'int *'
+}
+
+void test_unowned_function_calls() {
+  int stack_int = 42;
+  int *unowned_int1 = &stack_int;
+  gsl::owner<int *> owned_int1 = new int(42);
+
+  takes_pointer(&stack_int);   // Ok
+  takes_pointer(unowned_int1); // Ok
+  takes_pointer(owned_int1);   // Ok
+  takes_pointer(new int(42));  // Bad, since new creates and owner
+  // CHECK-MESSAGES: [[@LINE-1]]:17: warning: initializing non-owner argument of type 'int *' with a newly created 'gsl::owner<>'
+
+  takes_pointer(returns_owner1()); // Bad
+  // CHECK-MESSAGES: [[@LINE-1]]:17: warning: initializing non-owner argument of type 'int *' with a newly created 'gsl::owner<>'
+
+  takes_pointer(returns_no_owner1()); // Ok
+}
+
+// FIXME: Typedefing owner<> to something else does not work.
+// This might be necessary for code already having a similar typedef like owner<> and
+// replacing it with owner<>. This might be the same problem as with templates.
+// The canonical type will ignore the owner<> alias, since its a typedef as well.
+//
+// Check, if owners hidden by typedef are handled the same as 'obvious' owners.
+#if 0
+using heap_int = gsl::owner<int *>;
+typedef gsl::owner<float *> heap_float;
+
+// This tests only a subset, assuming that the check will either see through the
+// typedef or not (it doesn't!).
+void test_typedefed_values() {
+  // Modern typedef.
+  int StackInt1 = 42;
+  heap_int HeapInt1 = &StackInt1;
+  // CHECK MESSAGES: [[@LINE-1]]:3: warning: expected assignment source to be of type 'gsl::owner<>'; got 'int *'
+
+  //FIXME: Typedef not considered correctly here.
+  // heap_int HeapInt2 = new int(42); // Ok
+  takes_pointer(HeapInt1); // Ok
+  takes_owner(HeapInt1);   // Ok
+
+  // Traditional typedef.
+  float StackFloat1 = 42.0f;
+  heap_float HeapFloat1 = &StackFloat1;
+  // CHECK MESSAGES: [[@LINE-1]]:3: warning: expected assignment source to be of type 'gsl::owner<>'; got 'float *'
+
+  //FIXME: Typedef not considered correctly here.
+  // heap_float HeapFloat2 = new float(42.0f);
+  HeapFloat2 = HeapFloat1; // Ok
+}
+#endif
+
+struct ArbitraryClass {};
+struct ClassWithOwner {                    // Does not define destructor, necessary with owner
+  ClassWithOwner() : owner_var(nullptr) {} // Ok
+
+  ClassWithOwner(ArbitraryClass &other) : owner_var(&other) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:43: warning: expected initialization of owner member variable with value of type 'gsl::owner<>'; got 'ArbitraryClass *'
+
+  ClassWithOwner(gsl::owner<ArbitraryClass *> other) : owner_var(other) {} // Ok
+
+  ClassWithOwner(gsl::owner<ArbitraryClass *> data, int /* unused */) { // Ok
+    owner_var = data;                                                   // Ok
+  }
+
+  ClassWithOwner(ArbitraryClass *bad_data, int /* unused */, int /* unused */) {
+    owner_var = bad_data;
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: expected assignment source to be of type 'gsl::owner<>'; got 'ArbitraryClass *'
+  }
+
+  ClassWithOwner(ClassWithOwner &&other) : owner_var{other.owner_var} {} // Ok
+
+  ClassWithOwner &operator=(ClassWithOwner &&other) {
+    owner_var = other.owner_var; // Ok
+    return *this;
+  }
+
+  // Returning means, that the owner is "moved", so the class should not access this
+  // variable anymore after this method gets called.
+  gsl::owner<ArbitraryClass *> buggy_but_returns_owner() { return owner_var; }
+
+  gsl::owner<ArbitraryClass *> owner_var;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: member variable of type 'gsl::owner<>' requires the class 'ClassWithOwner' to implement a destructor to release the owned resource
+};
+
+class DefaultedDestructor {         // Bad since default constructor with owner
+  ~DefaultedDestructor() = default; // Bad, since will not destroy the owner
+  gsl::owner<int *> Owner;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: member variable of type 'gsl::owner<>' requires the class 'DefaultedDestructor' to implement a destructor to release the owned resource
+};
+
+struct DeletedDestructor {
+  ~DeletedDestructor() = delete;
+  gsl::owner<int *> Owner;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: member variable of type 'gsl::owner<>' requires the class 'DeletedDestructor' to implement a destructor to release the owned resource
+};
+
+void test_class_with_owner() {
+  ArbitraryClass A;
+  ClassWithOwner C1;                                                   // Ok
+  ClassWithOwner C2{A};                                                // Bad, since the owner would be initialized with an non-owner, but catched in the class
+  ClassWithOwner C3{gsl::owner<ArbitraryClass *>(new ArbitraryClass)}; // Ok
+
+  const auto Owner1 = C3.buggy_but_returns_owner(); // BAD, deduces Owner1 to ArbitraryClass *const
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'ArbitraryClass *const' with a newly created 'gsl::owner<>'
+  // CHECK-MESSAGES: [[@LINE-2]]:3: note: type deduction did not result in an owner
+
+  auto Owner2 = C2.buggy_but_returns_owner(); // BAD, deduces Owner2 to ArbitraryClass *
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: initializing non-owner 'ArbitraryClass *' with a newly created 'gsl::owner<>'
+  // CHECK-MESSAGES: [[@LINE-2]]:3: note: type deduction did not result in an owner
+
+  Owner2 = &A; // Ok, since type deduction did NOT result in owner<int*>
+
+  gsl::owner<ArbitraryClass *> Owner3 = C1.buggy_but_returns_owner(); // Ok, still an owner
+  Owner3 = &A;                                                        // Bad, since assignment of non-owner to owner
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected assignment source to be of type 'gsl::owner<>'; got 'ArbitraryClass *'
+}
+
+template <typename T>
+struct HeapArray {                                          // Ok, since destructor with owner
+  HeapArray() : _data(nullptr), size(0) {}                  // Ok
+  HeapArray(int size) : _data(new int[size]), size(size) {} // Ok
+  HeapArray(int size, T val) {
+    _data = new int[size]; // Ok
+    size = size;
+    for (auto i = 0u; i < size; ++i)
+      _data[i] = val; // Ok
+  }
+  HeapArray(int size, T val, int *problematic) : _data{problematic}, size(size) {} // Bad
+  // CHECK-MESSAGES: [[@LINE-1]]:50: warning: expected initialization of owner member variable with value of type 'gsl::owner<>'; got 'void'
+  // FIXME: void is incorrect type, probably wrong thing matched
+
+  HeapArray(HeapArray &&other) : _data(other._data), size(other.size) { // Ok
+    other._data = nullptr;                                              // Ok
+    other.size = 0;
+  }
+
+  HeapArray<T> &operator=(HeapArray<T> &&other) {
+    _data = other._data; // Ok, NOLINT warning here about bad types, why?
+    size = other.size;
+    return *this;
+  }
+
+  ~HeapArray() { delete[] _data; } // Ok
+
+  T *data() { return _data; } // Ok NOLINT, because it "looks" like a factory
+
+  gsl::owner<T *> _data;
+  unsigned int size;
+};
+
+void test_inner_template() {
+  HeapArray<int> Array1;
+  HeapArray<int> Array2(100);
+  HeapArray<int> Array3(100, 0);
+  HeapArray<int> Array4(100, 0, nullptr);
+
+  Array1 = static_cast<HeapArray<int> &&>(Array2);
+  HeapArray<int> Array5(static_cast<HeapArray<int> &&>(Array3));
+
+  int *NonOwningPtr = Array1.data();           // Ok
+  gsl::owner<int *> OwningPtr = Array1.data(); // Bad, since it does not return the owner
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'int *'
+}
+
+// FIXME: Typededuction removes the owner - wrapper, therefore gsl::owner can not be used
+// with Template classes like this. Is there a walkaround?
+template <typename T>
+struct TemplateValue {
+  TemplateValue() = default;
+  TemplateValue(T t) : val{t} {}
+
+  void setVal(const T &t) { val = t; }
+  const T getVal() const { return val; }
+
+  T val;
+};
+
+// FIXME: Same typededcution problems
+template <typename T>
+void template_function(T t) {
+  gsl::owner<int *> owner_t = t; // Probably bad, since type deduction still wrong
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'T'
+  // CHECK-MESSAGES: [[@LINE-2]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'int *'
+}
+
+// FIXME: Same typededcution problems
+void test_templates() {
+  int stack_int = 42;
+  int *stack_ptr1 = &stack_int;
+
+  TemplateValue<gsl::owner<int *>> Owner0; // Ok, T should be owner, but is int*
+
+  TemplateValue<gsl::owner<int *>> Owner1(new int(42)); // Ok, T should be owner, but is int*
+  Owner1.setVal(&stack_int);                            // Bad since non-owner assignment
+  Owner1.setVal(stack_ptr1);                            // Bad since non-owner assignment
+  //Owner1.setVal(new int(42)); // Ok, but since type deduction is wrong, this one is considered harmful
+
+  int *stack_ptr2 = Owner1.getVal(); // Bad, initializing non-owner with owner
+
+  TemplateValue<int *> NonOwner1(new int(42));      // Bad, T is int *, hence dynamic memory to non-owner
+  gsl::owner<int *> IntOwner1 = NonOwner1.getVal(); // Bad, since owner initialized with non-owner
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: expected initialization with value of type 'gsl::owner<>'; got 'int *'
+
+  template_function(IntOwner1);  // Ok, but not actually ok, since type deduction removes owner
+  template_function(stack_ptr1); // Bad, but type deduction gets it wrong
+}
diff --git a/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp b/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
index 08481a8..bd2fdc1 100644
--- a/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
+++ b/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
@@ -312,6 +312,19 @@
   // CHECK-FIXES-NOT: float Y{};
 };
 
+union PositiveUnionReversed {
+  PositiveUnionReversed() : X() {} // No message as a union can only initialize one member.
+  PositiveUnionReversed(int) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: union constructor should initialize one of these fields: Y, X
+
+  // Make sure we don't give Y an initializer.
+  TestEnum Y;
+  // CHECK-FIXES-NOT: TestEnum Y{};
+
+  int X;
+  // CHECK-FIXES: int X{};
+};
+
 struct PositiveAnonymousUnionAndStruct {
   PositiveAnonymousUnionAndStruct() {}
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A, B, Y, Z, C, D, E, F, X
@@ -473,3 +486,16 @@
   unsigned F : 5;
   unsigned G : 5;
 };
+
+struct NegativeImplicitInheritedCtorBase {
+  NegativeImplicitInheritedCtorBase(unsigned F) : F(F) {}
+  unsigned F;
+};
+
+struct NegativeImplicitInheritedCtor : NegativeImplicitInheritedCtorBase {
+  using NegativeImplicitInheritedCtorBase::NegativeImplicitInheritedCtorBase;
+};
+
+void Bug33557() {
+  NegativeImplicitInheritedCtor I(5);
+}
diff --git a/test/clang-tidy/diagnostic.cpp b/test/clang-tidy/diagnostic.cpp
index 9c30b14..656e05b 100644
--- a/test/clang-tidy/diagnostic.cpp
+++ b/test/clang-tidy/diagnostic.cpp
@@ -1,18 +1,39 @@
 // RUN: clang-tidy -checks='-*,modernize-use-override' %s.nonexistent.cpp -- | FileCheck -check-prefix=CHECK1 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %s -- -fan-unknown-option | FileCheck -check-prefix=CHECK2 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: clang-tidy -checks='-*,google-explicit-constructor,clang-diagnostic-literal-conversion' %s -- -fan-unknown-option | FileCheck -check-prefix=CHECK3 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined' %s -- -DMACRO_FROM_COMMAND_LINE | FileCheck -check-prefix=CHECK4 -implicit-check-not='{{warning:|error:}}' %s
+//
+// Now repeat the tests and ensure no other errors appear on stderr:
+// RUN: clang-tidy -checks='-*,modernize-use-override' %s.nonexistent.cpp -- 2>&1 | FileCheck -check-prefix=CHECK1 -implicit-check-not='{{warning:|error:}}' %s
 // RUN: clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %s -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK2 -implicit-check-not='{{warning:|error:}}' %s
 // RUN: clang-tidy -checks='-*,google-explicit-constructor,clang-diagnostic-literal-conversion' %s -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK3 -implicit-check-not='{{warning:|error:}}' %s
-// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined' %s -- -DMACRO_FROM_COMMAND_LINE | FileCheck -check-prefix=CHECK4 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined' %s -- -DMACRO_FROM_COMMAND_LINE 2>&1 | FileCheck -check-prefix=CHECK4 -implicit-check-not='{{warning:|error:}}' %s
+//
+// Now create a directory with a compilation database file and ensure we don't
+// use it after failing to parse commands from the command line:
+//
+// RUN: mkdir -p %T/diagnostics/
+// RUN: echo '[{"directory": "%/T/diagnostics/","command": "clang++ -fan-option-from-compilation-database -c %/T/diagnostics/input.cpp", "file": "%/T/diagnostics/input.cpp"}]' > %T/diagnostics/compile_commands.json
+// RUN: cat %s > %T/diagnostics/input.cpp
+// RUN: clang-tidy -checks='-*,modernize-use-override' %T/diagnostics/nonexistent.cpp -- 2>&1 | FileCheck -check-prefix=CHECK1 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %T/diagnostics/input.cpp -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK2 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: clang-tidy -checks='-*,google-explicit-constructor,clang-diagnostic-literal-conversion' %T/diagnostics/input.cpp -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK3 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined' %T/diagnostics/input.cpp -- -DMACRO_FROM_COMMAND_LINE 2>&1 | FileCheck -check-prefix=CHECK4 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %T/diagnostics/input.cpp 2>&1 | FileCheck -check-prefix=CHECK5 -implicit-check-not='{{warning:|error:}}' %s
 
-// CHECK1: error: error reading '{{.*}}.nonexistent.cpp' [clang-diagnostic-error]
-// CHECK2: error: unknown argument: '-fan-unknown-option'
-// CHECK3: error: unknown argument: '-fan-unknown-option'
+// CHECK1: error: error reading '{{.*}}nonexistent.cpp' [clang-diagnostic-error]
+// CHECK2: error: unknown argument: '-fan-unknown-option' [clang-diagnostic-error]
+// CHECK3: error: unknown argument: '-fan-unknown-option' [clang-diagnostic-error]
+// CHECK5: error: unknown argument: '-fan-option-from-compilation-database' [clang-diagnostic-error]
 
-// CHECK2: :[[@LINE+2]]:9: warning: implicit conversion from 'double' to 'int' changes value from 1.5 to 1 [clang-diagnostic-literal-conversion]
-// CHECK3: :[[@LINE+1]]:9: warning: implicit conversion from 'double' to 'int' changes value
+// CHECK2: :[[@LINE+3]]:9: warning: implicit conversion from 'double' to 'int' changes value from 1.5 to 1 [clang-diagnostic-literal-conversion]
+// CHECK3: :[[@LINE+2]]:9: warning: implicit conversion from 'double' to 'int' changes value
+// CHECK5: :[[@LINE+1]]:9: warning: implicit conversion from 'double' to 'int' changes value
 int a = 1.5;
 
-// CHECK2: :[[@LINE+2]]:11: warning: single-argument constructors must be marked explicit
-// CHECK3: :[[@LINE+1]]:11: warning: single-argument constructors must be marked explicit
+// CHECK2: :[[@LINE+3]]:11: warning: single-argument constructors must be marked explicit
+// CHECK3: :[[@LINE+2]]:11: warning: single-argument constructors must be marked explicit
+// CHECK5: :[[@LINE+1]]:11: warning: single-argument constructors must be marked explicit
 class A { A(int) {} };
 
 #define MACRO_FROM_COMMAND_LINE
diff --git a/test/clang-tidy/google-readability-casting.cpp b/test/clang-tidy/google-readability-casting.cpp
index a4d29d6..d36fef6 100644
--- a/test/clang-tidy/google-readability-casting.cpp
+++ b/test/clang-tidy/google-readability-casting.cpp
@@ -85,6 +85,22 @@
   // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast [
   // CHECK-FIXES: b1 = (const int&)b;
 
+  b1 = (int) b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}}; use static_cast {{.*}}
+  // CHECK-FIXES: b1 = static_cast<int>(b);
+
+  b1 = (int)         b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}}; use static_cast {{.*}}
+  // CHECK-FIXES: b1 = static_cast<int>(b);
+
+  b1 = (int) (b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}}; use static_cast {{.*}}
+  // CHECK-FIXES: b1 = static_cast<int>(b);
+
+  b1 = (int)         (b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}}; use static_cast {{.*}}
+  // CHECK-FIXES: b1 = static_cast<int>(b);
+
   Y *pB = (Y*)pX;
   // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast [
   Y &rB = (Y&)*pX;
@@ -114,6 +130,14 @@
   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant cast to the same type
   // CHECK-FIXES: {{^}}  e = e;
 
+  e = (Enum)           e;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant cast to the same type
+  // CHECK-FIXES: {{^}}  e = e;
+
+  e = (Enum)           (e);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant cast to the same type
+  // CHECK-FIXES: {{^}}  e = (e);
+
   static const int kZero = 0;
   (int)kZero;
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant cast to the same type
diff --git a/test/clang-tidy/google-readability-namespace-comments.cpp b/test/clang-tidy/google-readability-namespace-comments.cpp
index a9a6fdd..9abb984 100644
--- a/test/clang-tidy/google-readability-namespace-comments.cpp
+++ b/test/clang-tidy/google-readability-namespace-comments.cpp
@@ -15,6 +15,20 @@
 // CHECK-FIXES: }  // namespace n2
 // CHECK-FIXES: }  // namespace n1
 
+#define MACRO macro_expansion
+namespace MACRO {
+void f(); // So that the namespace isn't empty.
+// 1
+// 2
+// 3
+// 4
+// 5
+// 6
+// 7
+// CHECK-MESSAGES: :[[@LINE+2]]:2: warning: namespace 'macro_expansion' not terminated with
+// CHECK-MESSAGES: :[[@LINE-10]]:11: note: namespace 'macro_expansion' starts here
+}
+// CHECK-FIXES: }  // namespace macro_expansion
 
 namespace short1 {
 namespace short2 {
diff --git a/test/clang-tidy/google-runtime-memset-zero-length.cpp b/test/clang-tidy/google-runtime-memset-zero-length.cpp
deleted file mode 100644
index 7599c75..0000000
--- a/test/clang-tidy/google-runtime-memset-zero-length.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-// RUN: %check_clang_tidy %s google-runtime-memset %t
-
-void *memset(void *, int, __SIZE_TYPE__);
-
-namespace std {
-  using ::memset;
-}
-
-template <int i, typename T>
-void memtmpl() {
-  memset(0, sizeof(int), i);
-  memset(0, sizeof(T), sizeof(T));
-  memset(0, sizeof(T), 0);
-// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped argument
-// CHECK-FIXES: memset(0, 0, sizeof(T));
-  memset(0, sizeof(int), 0);
-// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped argument
-// CHECK-FIXES: memset(0, 0, sizeof(int));
-}
-
-void foo(void *a, int xsize, int ysize) {
-  memset(a, sizeof(int), 0);
-// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped argument
-// CHECK-FIXES: memset(a, 0, sizeof(int));
-#define M memset(a, sizeof(int), 0);
-  M
-// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped argument
-// CHECK-FIXES: #define M memset(a, sizeof(int), 0);
-  ::memset(a, xsize *
-           ysize, 0);
-// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: memset of size zero, potentially swapped argument
-// CHECK-FIXES: ::memset(a, 0, xsize *
-// CHECK-FIXES-NEXT: ysize);
-  std::memset(a, sizeof(int), 0x00);
-// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped argument
-// CHECK-FIXES: std::memset(a, 0x00, sizeof(int));
-
-  const int v = 0;
-  memset(a, sizeof(int), v);
-// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped argument
-// CHECK-FIXES: memset(a, v, sizeof(int));
-
-  memset(a, sizeof(int), v + v);
-// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped argument
-// CHECK-FIXES: memset(a, v + v, sizeof(int));
-
-  memset(a, sizeof(int), v + 1);
-
-  memset(a, -1, sizeof(int));
-  memset(a, 0xcd, 1);
-
-  // Don't warn when the fill char and the length are both known to be
-  // zero.  No bug is possible.
-  memset(a, 0, v);
-  memset(a, v, 0);
-
-  // -1 is clearly not a length by virtue of being negative, so no warning
-  // despite v == 0.
-  memset(a, -1, v);
-
-  memtmpl<0, int>();
-}
diff --git a/test/clang-tidy/hicpp-exception-baseclass.cpp b/test/clang-tidy/hicpp-exception-baseclass.cpp
new file mode 100644
index 0000000..9a0638b
--- /dev/null
+++ b/test/clang-tidy/hicpp-exception-baseclass.cpp
@@ -0,0 +1,179 @@
+// RUN: %check_clang_tidy %s hicpp-exception-baseclass %t -- -- -fcxx-exceptions
+
+namespace std {
+class exception {};
+} // namespace std
+
+class derived_exception : public std::exception {};
+class deep_hierarchy : public derived_exception {};
+class non_derived_exception {};
+class terrible_idea : public non_derived_exception, public derived_exception {};
+
+// FIXME: More complicated kinds of inheritance should be checked later, but there is
+// currently no way use ASTMatchers for this kind of task.
+#if 0
+class bad_inheritance : private std::exception {};
+class no_good_inheritance : protected std::exception {};
+class really_creative : public non_derived_exception, private std::exception {};
+#endif
+
+void problematic() {
+  try {
+    throw int(42);
+    // CHECK-MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
+  } catch (int e) {
+  }
+  throw int(42);
+  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
+
+  try {
+    throw 12;
+    // CHECK-MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
+  } catch (...) {
+    throw; // Ok, even if the type is not known, conforming code can never rethrow a non-std::exception object.
+  }
+
+  try {
+    throw non_derived_exception();
+    // CHECK-MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'non_derived_exception' is not derived from 'std::exception'
+    // CHECK-MESSAGES: 9:1: note: type defined here
+  } catch (non_derived_exception &e) {
+  }
+  throw non_derived_exception();
+  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'non_derived_exception' is not derived from 'std::exception'
+  // CHECK-MESSAGES: 9:1: note: type defined here
+
+// FIXME: More complicated kinds of inheritance should be checked later, but there is
+// currently no way use ASTMatchers for this kind of task.
+#if 0
+  // Handle private inheritance cases correctly.
+  try {
+    throw bad_inheritance();
+    // CHECK MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'bad_inheritance' is not derived from 'std::exception'
+    // CHECK MESSAGES: 10:1: note: type defined here
+    throw no_good_inheritance();
+    // CHECK MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'no_good_inheritance' is not derived from 'std::exception'
+    // CHECK MESSAGES: 11:1: note: type defined here
+    throw really_creative();
+    // CHECK MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'really_creative' is not derived from 'std::exception'
+    // CHECK MESSAGES: 12:1: note: type defined here
+  } catch (...) {
+  }
+  throw bad_inheritance();
+  // CHECK MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'bad_inheritance' is not derived from 'std::exception'
+  // CHECK MESSAGES: 10:1: note: type defined here
+  throw no_good_inheritance();
+  // CHECK MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'no_good_inheritance' is not derived from 'std::exception'
+  // CHECK MESSAGES: 11:1: note: type defined here
+  throw really_creative();
+  // CHECK MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'really_creative' is not derived from 'std::exception'
+  // CHECK MESSAGES: 12:1: note: type defined here
+#endif
+}
+
+void allowed_throws() {
+  try {
+    throw std::exception();     // Ok
+  } catch (std::exception &e) { // Ok
+  }
+  throw std::exception();
+
+  try {
+    throw derived_exception();     // Ok
+  } catch (derived_exception &e) { // Ok
+  }
+  throw derived_exception(); // Ok
+
+  try {
+    throw deep_hierarchy();     // Ok, multiple levels of inheritance
+  } catch (deep_hierarchy &e) { // Ok
+  }
+  throw deep_hierarchy(); // Ok
+
+  try {
+    throw terrible_idea();     // Ok, but multiple inheritance isn't clean
+  } catch (std::exception &e) { // Can be caught as std::exception, even with multiple inheritance
+  }
+  throw terrible_idea(); // Ok, but multiple inheritance
+}
+
+// Templated function that throws exception based on template type
+template <typename T>
+void ThrowException() { throw T(); }
+// CHECK-MESSAGES: [[@LINE-1]]:31: warning: throwing an exception whose type 'bad_generic_exception<int>' is not derived from 'std::exception'
+// CHECK-MESSAGES: 120:1: note: type defined here
+// CHECK-MESSAGES: [[@LINE-3]]:31: warning: throwing an exception whose type 'bad_generic_exception<std::exception>' is not derived from 'std::exception'
+// CHECK-MESSAGES: 120:1: note: type defined here
+// CHECK-MESSAGES: [[@LINE-5]]:31: warning: throwing an exception whose type 'exotic_exception<non_derived_exception>' is not derived from 'std::exception'
+// CHECK-MESSAGES: 123:1: note: type defined here
+// CHECK-MESSAGES: [[@LINE-7]]:31: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
+// CHECK-MESSAGES: [[@LINE-8]]:31: warning: throwing an exception whose type 'non_derived_exception' is not derived from 'std::exception'
+// CHECK-MESSAGES: 9:1: note: type defined here
+#define THROW_EXCEPTION(CLASS) ThrowException<CLASS>()
+#define THROW_BAD_EXCEPTION throw int(42);
+#define THROW_GOOD_EXCEPTION throw std::exception();
+#define THROW_DERIVED_EXCEPTION throw deep_hierarchy();
+
+template <typename T>
+class generic_exception : std::exception {};
+
+template <typename T>
+class bad_generic_exception {};
+
+template <typename T>
+class exotic_exception : public T {};
+
+void generic_exceptions() {
+  THROW_EXCEPTION(int);
+  // CHECK MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
+  THROW_EXCEPTION(non_derived_exception);
+  // CHECK MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'non_derived_exception' is not derived from 'std::exception'
+  // CHECK MESSAGES: 9:1: note: type defined here
+  THROW_EXCEPTION(std::exception);    // Ok
+  THROW_EXCEPTION(derived_exception); // Ok
+  THROW_EXCEPTION(deep_hierarchy);    // Ok
+
+  THROW_BAD_EXCEPTION;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
+  // CHECK-MESSAGES: [[@LINE-25]]:35: note: expanded from macro 'THROW_BAD_EXCEPTION'
+  THROW_GOOD_EXCEPTION;
+  THROW_DERIVED_EXCEPTION;
+
+  throw generic_exception<int>();            // Ok,
+  THROW_EXCEPTION(generic_exception<float>); // Ok
+
+  throw bad_generic_exception<int>();
+  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'bad_generic_exception<int>' is not derived from 'std::exception'
+  throw bad_generic_exception<std::exception>();
+  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'bad_generic_exception<std::exception>' is not derived from 'std::exception'
+  THROW_EXCEPTION(bad_generic_exception<int>);
+  // CHECK MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'bad_generic_exception<int>' is not derived from 'std::exception'
+  THROW_EXCEPTION(bad_generic_exception<std::exception>);
+  // CHECK MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'bad_generic_exception<std::exception>' is not derived from 'std::exception'
+
+  throw exotic_exception<non_derived_exception>();
+  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'exotic_exception<non_derived_exception>' is not derived from 'std::exception'
+  THROW_EXCEPTION(exotic_exception<non_derived_exception>);
+  // CHECK MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'exotic_exception<non_derived_exception>' is not derived from 'std::exception'
+
+  throw exotic_exception<derived_exception>();          // Ok
+  THROW_EXCEPTION(exotic_exception<derived_exception>); // Ok
+}
+
+// Test for typedefed exception types
+typedef int TypedefedBad;
+typedef derived_exception TypedefedGood;
+using UsingBad = int;
+using UsingGood = deep_hierarchy;
+
+void typedefed() {
+  throw TypedefedBad();
+  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'TypedefedBad' (aka 'int') is not derived from 'std::exception'
+  // CHECK-MESSAGES: 164:1: note: type defined here
+  throw TypedefedGood(); // Ok
+
+  throw UsingBad();
+  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'UsingBad' (aka 'int') is not derived from 'std::exception'
+  // CHECK-MESSAGES: 166:1: note: type defined here
+  throw UsingGood(); // Ok
+}
diff --git a/test/clang-tidy/hicpp-signed-bitwise-bug34747.cpp b/test/clang-tidy/hicpp-signed-bitwise-bug34747.cpp
new file mode 100644
index 0000000..217df71
--- /dev/null
+++ b/test/clang-tidy/hicpp-signed-bitwise-bug34747.cpp
@@ -0,0 +1,29 @@
+// RUN: %check_clang_tidy %s hicpp-signed-bitwise %t --
+
+// Note: this test expects no diagnostics, but FileCheck cannot handle that,
+// hence the use of | count 0.
+
+template <typename C>
+struct OutputStream {
+  OutputStream &operator<<(C);
+};
+
+template <typename C>
+struct foo {
+  typedef OutputStream<C> stream_type;
+  foo(stream_type &o) {
+    o << 'x'; // warning occured here, fixed now
+  }
+};
+
+void bar(OutputStream<signed char> &o) {
+  foo<signed char> f(o);
+}
+
+void silence_lit() {
+  int SValue = 42;
+  int SResult;
+
+  SResult = SValue & 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+}
diff --git a/test/clang-tidy/hicpp-signed-bitwise.cpp b/test/clang-tidy/hicpp-signed-bitwise.cpp
new file mode 100644
index 0000000..469256d
--- /dev/null
+++ b/test/clang-tidy/hicpp-signed-bitwise.cpp
@@ -0,0 +1,219 @@
+// RUN: %check_clang_tidy %s hicpp-signed-bitwise %t -- -- -std=c++11 --target=x86_64-linux
+
+// These could cause false positives and should not be considered.
+struct StreamClass {
+};
+StreamClass &operator<<(StreamClass &os, unsigned int i) {
+  return os;
+}
+StreamClass &operator<<(StreamClass &os, int i) {
+  return os;
+}
+StreamClass &operator>>(StreamClass &os, unsigned int i) {
+  return os;
+}
+StreamClass &operator>>(StreamClass &os, int i) {
+  return os;
+}
+struct AnotherStream {
+  AnotherStream &operator<<(unsigned char c) { return *this; }
+  AnotherStream &operator<<(signed char c) { return *this; }
+
+  AnotherStream &operator>>(unsigned char c) { return *this; }
+  AnotherStream &operator>>(signed char c) { return *this; }
+};
+
+void binary_bitwise() {
+  int SValue = 42;
+  int SResult;
+
+  unsigned int UValue = 42;
+  unsigned int UResult;
+
+  SResult = SValue & 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  SResult = SValue & -1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  SResult = SValue & SValue;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+
+  UResult = SValue & 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  UResult = SValue & -1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+
+  UResult = UValue & 1u;     // Ok
+  UResult = UValue & UValue; // Ok
+
+  unsigned char UByte1 = 0u;
+  unsigned char UByte2 = 16u;
+  signed char SByte1 = 0;
+  signed char SByte2 = 16;
+
+  UByte1 = UByte1 & UByte2; // Ok
+  UByte1 = SByte1 & UByte2;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator
+  UByte1 = SByte1 & SByte2;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator
+  SByte1 = SByte1 & SByte2;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator
+
+  // More complex expressions.
+  UResult = UValue & (SByte1 + (SByte1 | SByte2));
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator
+  // CHECK-MESSAGES: :[[@LINE-2]]:33: warning: use of a signed integer operand with a binary bitwise operator
+
+  // The rest is to demonstrate functionality but all operators are matched equally.
+  // Therefore functionality is the same for all binary operations.
+  UByte1 = UByte1 | UByte2; // Ok
+  UByte1 = UByte1 | SByte2;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator
+
+  UByte1 = UByte1 ^ UByte2; // Ok
+  UByte1 = UByte1 ^ SByte2;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator
+
+  UByte1 = UByte1 >> UByte2; // Ok
+  UByte1 = UByte1 >> SByte2;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator
+
+  UByte1 = UByte1 << UByte2; // Ok
+  UByte1 = UByte1 << SByte2;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator
+
+  int SignedInt1 = 1 << 12;
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use of a signed integer operand with a binary bitwise operator
+  int SignedInt2 = 1u << 12;
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use of a signed integer operand with a binary bitwise operator
+}
+
+void f1(unsigned char c) {}
+void f2(signed char c) {}
+void f3(int c) {}
+
+void unary_bitwise() {
+  unsigned char UByte1 = 0u;
+  signed char SByte1 = 0;
+
+  UByte1 = ~UByte1; // Ok
+  SByte1 = ~UByte1;
+  SByte1 = ~SByte1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a unary bitwise operator
+  UByte1 = ~SByte1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a unary bitwise operator
+
+  unsigned int UInt = 0u;
+  int SInt = 0;
+
+  f1(~UByte1); // Ok
+  f1(~SByte1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use of a signed integer operand with a unary bitwise operator
+  f1(~UInt);
+  f1(~SInt);
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use of a signed integer operand with a unary bitwise operator
+  f2(~UByte1);
+  f2(~SByte1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use of a signed integer operand with a unary bitwise operator
+  f2(~UInt);
+  f2(~SInt);
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use of a signed integer operand with a unary bitwise operator
+  f3(~UByte1); // Ok
+  f3(~SByte1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use of a signed integer operand with a unary bitwise operator
+}
+
+/// HICPP uses these examples to demonstrate the rule.
+void standard_examples() {
+  int i = 3;
+  unsigned int k = 0u;
+
+  int r = i << -1; // Emits -Wshift-count-negative from clang
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use of a signed integer operand with a binary bitwise operator
+  r = i << 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use of a signed integer operand with a binary bitwise operator
+
+  r = -1 >> -1; // Emits -Wshift-count-negative from clang
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use of a signed integer operand with a binary bitwise operator
+  r = -1 >> 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use of a signed integer operand with a binary bitwise operator
+
+  r = -1 >> i;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use of a signed integer operand with a binary bitwise operator
+  r = -1 >> -i;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use of a signed integer operand with a binary bitwise operator
+
+  r = ~0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use of a signed integer operand with a unary bitwise operator
+  r = ~0u; // Ok
+  k = ~k;  // Ok
+
+  unsigned int u = (-1) & 2u;
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use of a signed integer operand with a binary bitwise operator
+  u = (-1) | 1u;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use of a signed integer operand with a binary bitwise operator
+  u = (-1) ^ 1u;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use of a signed integer operand with a binary bitwise operator
+}
+
+void streams_should_work() {
+  StreamClass s;
+  s << 1u; // Ok
+  s << 1;  // Ok
+  s >> 1;  // Ok
+  s >> 1u; // Ok
+
+  AnotherStream as;
+  unsigned char uc = 1u;
+  signed char sc = 1;
+  as << uc; // Ok
+  as << sc; // Ok
+  as >> uc; // Ok
+  as >> sc; // Ok
+}
+
+enum OldEnum {
+  ValueOne,
+  ValueTwo,
+};
+
+enum OldSigned : int {
+  IntOne,
+  IntTwo,
+};
+
+void classicEnums() {
+  OldEnum e1 = ValueOne, e2 = ValueTwo;
+  int e3;                   // Using the enum type, results in an error.
+  e3 = ValueOne | ValueTwo; // Ok
+  e3 = ValueOne & ValueTwo; // Ok
+  e3 = ValueOne ^ ValueTwo; // Ok
+  e3 = e1 | e2;             // Ok
+  e3 = e1 & e2;             // Ok
+  e3 = e1 ^ e2;             // Ok
+
+  OldSigned s1 = IntOne, s2 = IntTwo;
+  int s3;
+  s3 = IntOne | IntTwo; // Signed
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: use of a signed integer operand with a binary bitwise operator
+  s3 = IntOne & IntTwo; // Signed
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: use of a signed integer operand with a binary bitwise operator
+  s3 = IntOne ^ IntTwo; // Signed
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: use of a signed integer operand with a binary bitwise operator
+  s3 = s1 | s2; // Signed
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: use of a signed integer operand with a binary bitwise operator
+  s3 = s1 & s2; // Signed
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: use of a signed integer operand with a binary bitwise operator
+  s3 = s1 ^ s2; // Signed
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: use of a signed integer operand with a binary bitwise operator
+}
+
+enum EnumConstruction {
+  one = 1,
+  two = 2,
+  test1 = 1 << 12,
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: use of a signed integer operand with a binary bitwise operator
+  test2 = one << two,
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: use of a signed integer operand with a binary bitwise operator
+  test3 = 1u << 12,
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: use of a signed integer operand with a binary bitwise operator
+};
diff --git a/test/clang-tidy/misc-definitions-in-headers-1z.hpp b/test/clang-tidy/misc-definitions-in-headers-1z.hpp
new file mode 100644
index 0000000..79fb7bc
--- /dev/null
+++ b/test/clang-tidy/misc-definitions-in-headers-1z.hpp
@@ -0,0 +1,10 @@
+// RUN: %check_clang_tidy %s misc-definitions-in-headers %t -- -- -std=c++1z
+
+class CE {
+  constexpr static int i = 5; // OK: inline variable definition.
+};
+
+inline int i = 5; // OK: inline variable definition.
+
+int b = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'b' defined in a header file; variable definitions in header files can lead to ODR violations [misc-definitions-in-headers]
diff --git a/test/clang-tidy/misc-definitions-in-headers.hpp b/test/clang-tidy/misc-definitions-in-headers.hpp
index d0dda95..5e83e68 100644
--- a/test/clang-tidy/misc-definitions-in-headers.hpp
+++ b/test/clang-tidy/misc-definitions-in-headers.hpp
@@ -175,3 +175,7 @@
 int CD<T, int>::f() { // OK: partial template specialization.
   return 0;
 }
+
+constexpr int k = 1; // OK: constexpr variable has internal linkage.
+
+constexpr int f10() { return 0; } // OK: constexpr function definition.
diff --git a/test/clang-tidy/misc-inefficient-algorithm.cpp b/test/clang-tidy/misc-inefficient-algorithm.cpp
index 75ca7d6..830c79c 100644
--- a/test/clang-tidy/misc-inefficient-algorithm.cpp
+++ b/test/clang-tidy/misc-inefficient-algorithm.cpp
@@ -43,19 +43,23 @@
 
 template <typename K, typename Cmp = less<K>> struct multiset : set<K, Cmp> {};
 
-template <typename FwIt, typename K> FwIt find(FwIt, FwIt, const K &);
+template <typename FwIt, typename K>
+FwIt find(FwIt, FwIt end, const K &) { return end; }
 
 template <typename FwIt, typename K, typename Cmp>
-FwIt find(FwIt, FwIt, const K &, Cmp);
+FwIt find(FwIt, FwIt end, const K &, Cmp) { return end; }
 
-template <typename FwIt, typename Pred> FwIt find_if(FwIt, FwIt, Pred);
+template <typename FwIt, typename Pred>
+FwIt find_if(FwIt, FwIt end, Pred) { return end; }
 
-template <typename FwIt, typename K> FwIt count(FwIt, FwIt, const K &);
+template <typename FwIt, typename K>
+unsigned count(FwIt, FwIt, const K &) { return 0; }
 
-template <typename FwIt, typename K> FwIt lower_bound(FwIt, FwIt, const K &);
+template <typename FwIt, typename K>
+FwIt lower_bound(FwIt, FwIt end, const K &) { return end; }
 
 template <typename FwIt, typename K, typename Ord>
-FwIt lower_bound(FwIt, FwIt, const K &, Ord);
+FwIt lower_bound(FwIt, FwIt end, const K &, Ord) { return end; }
 }
 
 #define FIND_IN_SET(x) find(x.begin(), x.end(), 10)
diff --git a/test/clang-tidy/misc-misplaced-widening-cast-explicit-only.cpp b/test/clang-tidy/misc-misplaced-widening-cast-explicit-only.cpp
index 6b236a7..dc66335 100644
--- a/test/clang-tidy/misc-misplaced-widening-cast-explicit-only.cpp
+++ b/test/clang-tidy/misc-misplaced-widening-cast-explicit-only.cpp
@@ -56,3 +56,9 @@
     return (long)a * 1000;
   }
 }
+
+// Shall not generate an assert. https://bugs.llvm.org/show_bug.cgi?id=33660
+template <class> class A {
+  enum Type {};
+  static char *m_fn1() { char p = (Type)(&p - m_fn1()); }
+};
diff --git a/test/clang-tidy/misc-move-const-arg.cpp b/test/clang-tidy/misc-move-const-arg.cpp
index 29b2b92..bbe6c6b 100644
--- a/test/clang-tidy/misc-move-const-arg.cpp
+++ b/test/clang-tidy/misc-move-const-arg.cpp
@@ -10,7 +10,9 @@
 template <typename _Tp> struct remove_reference<_Tp &&> { typedef _Tp type; };
 
 template <typename _Tp>
-constexpr typename std::remove_reference<_Tp>::type &&move(_Tp &&__t);
+constexpr typename std::remove_reference<_Tp>::type &&move(_Tp &&__t) {
+  return static_cast<typename std::remove_reference<_Tp>::type &&>(__t);
+}
 
 } // namespace std
 
diff --git a/test/clang-tidy/misc-suspicious-enum-usage.cpp b/test/clang-tidy/misc-suspicious-enum-usage.cpp
index 27e78f5..52d666d 100644
--- a/test/clang-tidy/misc-suspicious-enum-usage.cpp
+++ b/test/clang-tidy/misc-suspicious-enum-usage.cpp
@@ -54,7 +54,7 @@
   int emptytest = EmptyVal | B;
   if (bestDay() | A)
     return 1;
-  // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types 
+  // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types
   if (I | Y)
     return 1;
   // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different enum types
@@ -88,3 +88,9 @@
     return 1;
   return 42;
 }
+
+namespace PR34400 {
+enum { E1 = 0 };
+enum { E2 = -1 };
+enum { l = E1 | E2 };
+}
diff --git a/test/clang-tidy/misc-unused-parameters.cpp b/test/clang-tidy/misc-unused-parameters.cpp
index fc20b2b..b18aa20 100644
--- a/test/clang-tidy/misc-unused-parameters.cpp
+++ b/test/clang-tidy/misc-unused-parameters.cpp
@@ -14,16 +14,32 @@
 
 void b(int i = 1) {}
 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: parameter 'i' is unused [misc-unused-parameters]
-// CHECK-FIXES: {{^}}void b(int  /*i*/) {}{{$}}
+// CHECK-FIXES: {{^}}void b(int  /*i*/ = 1) {}{{$}}
 
 void c(int *i) {}
 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: parameter 'i' is unused [misc-unused-parameters]
 // CHECK-FIXES: {{^}}void c(int * /*i*/) {}{{$}}
 
+void d(int i[]) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: parameter 'i' is unused [misc-unused-parameters]
+// CHECK-FIXES: {{^}}void d(int  /*i*/[]) {}{{$}}
+
+void e(int i[1]) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: parameter 'i' is unused [misc-unused-parameters]
+// CHECK-FIXES: {{^}}void e(int  /*i*/[1]) {}{{$}}
+
+void f(void (*fn)()) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: parameter 'fn' is unused [misc-unused-parameters]
+// CHECK-FIXES: {{^}}void f(void (* /*fn*/)()) {}{{$}}
+
 // Unchanged cases
 // ===============
-void g(int i);             // Don't remove stuff in declarations
-void h(int i) { (void)i; } // Don't remove used parameters
+void f(int i); // Don't remove stuff in declarations
+void g(int i = 1);
+void h(int i[]);
+void s(int i[1]);
+void u(void (*fn)());
+void w(int i) { (void)i; } // Don't remove used parameters
 
 bool useLambda(int (*fn)(int));
 static bool static_var = useLambda([] (int a) { return a; });
@@ -52,6 +68,23 @@
 // CHECK-MESSAGES: :[[@LINE-1]]:33: warning
 // CHECK-FIXES: {{^}}static void staticFunctionE()
 
+static void staticFunctionF(int i = 4);
+// CHECK-FIXES: {{^}}static void staticFunctionF();
+static void staticFunctionF(int i) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning
+// CHECK-FIXES: {{^}}static void staticFunctionF()
+
+static void staticFunctionG(int i[]);
+// CHECK-FIXES: {{^}}static void staticFunctionG();
+static void staticFunctionG(int i[]) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning
+// CHECK-FIXES: {{^}}static void staticFunctionG()
+
+static void staticFunctionH(void (*fn)());
+// CHECK-FIXES: {{^}}static void staticFunctionH();
+static void staticFunctionH(void (*fn)()) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:36: warning
+// CHECK-FIXES: {{^}}static void staticFunctionH()
 
 static void someCallSites() {
   staticFunctionA(1);
@@ -62,7 +95,18 @@
 // CHECK-FIXES: staticFunctionC(2);
   staticFunctionD(1, 2, 3);
 // CHECK-FIXES: staticFunctionD(1, 3);
-  staticFunctionE();
+  staticFunctionE(1);
+// CHECK-FIXES: staticFunctionE();
+  staticFunctionF(1);
+// CHECK-FIXES: staticFunctionF();
+  staticFunctionF();
+// CHECK-FIXES: staticFunctionF();
+  int t[] = {1};
+  staticFunctionG(t);
+// CHECK-FIXES: staticFunctionG();
+  void func();
+  staticFunctionH(&func);
+// CHECK-FIXES: staticFunctionH();
 }
 
 /*
@@ -95,6 +139,15 @@
   static void f(int i) {}
 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning
 // CHECK-FIXES: static void f(int  /*i*/) {}
+  static void g(int i = 1) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning
+// CHECK-FIXES: static void g(int  /*i*/ = 1) {}
+  static void h(int i[]) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning
+// CHECK-FIXES: static void h(int  /*i*/[]) {}
+  static void s(void (*fn)()) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning
+// CHECK-FIXES: static void s(void (* /*fn*/)()) {}
 };
 
 namespace {
@@ -108,6 +161,15 @@
   void h(int i) {}
 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning
 // CHECK-FIXES: void h(int  /*i*/) {}
+  void s(int i = 1) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning
+// CHECK-FIXES: void s(int  /*i*/ = 1) {}
+  void u(int i[]) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning
+// CHECK-FIXES: void u(int  /*i*/[]) {}
+  void w(void (*fn)()) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning
+// CHECK-FIXES: void w(void (* /*fn*/)()) {}
 };
 
 void C::f(int i) {}
@@ -125,6 +187,9 @@
 // CHECK-FIXES: c.g();
 
   useFunction(&C::h);
+  useFunction(&C::s);
+  useFunction(&C::u);
+  useFunction(&C::w);
 }
 
 class Base {
diff --git a/test/clang-tidy/misc-use-after-move.cpp b/test/clang-tidy/misc-use-after-move.cpp
index 970364b..b0e96a6 100644
--- a/test/clang-tidy/misc-use-after-move.cpp
+++ b/test/clang-tidy/misc-use-after-move.cpp
@@ -723,6 +723,11 @@
     std::move(container);
     container.clear();
     container.empty();
+
+    auto container2 = container;
+    std::move(container2);
+    container2.clear();
+    container2.empty();
   }
   {
     std::deque<int> container;
diff --git a/test/clang-tidy/modernize-make-shared-header.cpp b/test/clang-tidy/modernize-make-shared-header.cpp
new file mode 100644
index 0000000..21b07ee
--- /dev/null
+++ b/test/clang-tidy/modernize-make-shared-header.cpp
@@ -0,0 +1,17 @@
+// RUN: %check_clang_tidy %s modernize-make-shared %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN:     [{key: modernize-make-shared.MakeSmartPtrFunction, \
+// RUN:       value: 'my::MakeShared'}, \
+// RUN:      {key: modernize-make-shared.MakeSmartPtrFunctionHeader, \
+// RUN:       value: 'make_shared_util.h'} \
+// RUN:     ]}" \
+// RUN:   -- -std=c++11 -I%S/Inputs/modernize-smart-ptr
+
+#include "shared_ptr.h"
+// CHECK-FIXES: #include "make_shared_util.h"
+
+void f() {
+  std::shared_ptr<int> P1 = std::shared_ptr<int>(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use my::MakeShared instead
+  // CHECK-FIXES: std::shared_ptr<int> P1 = my::MakeShared<int>();
+}
diff --git a/test/clang-tidy/modernize-make-shared.cpp b/test/clang-tidy/modernize-make-shared.cpp
index 4f47841..ed4da99 100644
--- a/test/clang-tidy/modernize-make-shared.cpp
+++ b/test/clang-tidy/modernize-make-shared.cpp
@@ -1,28 +1,8 @@
-// RUN: %check_clang_tidy %s modernize-make-shared %t
+// RUN: %check_clang_tidy %s modernize-make-shared %t -- -- -std=c++11 \
+// RUN:   -I%S/Inputs/modernize-smart-ptr
 
-namespace std {
-
-template <typename type>
-class shared_ptr {
-public:
-  shared_ptr();
-  shared_ptr(type *ptr);
-  shared_ptr(const shared_ptr<type> &t) {}
-  shared_ptr(shared_ptr<type> &&t) {}
-  ~shared_ptr();
-  type &operator*() { return *ptr; }
-  type *operator->() { return ptr; }
-  type *release();
-  void reset();
-  void reset(type *pt);
-  shared_ptr &operator=(shared_ptr &&);
-  template <typename T>
-  shared_ptr &operator=(shared_ptr<T> &&);
-
-private:
-  type *ptr;
-};
-}
+#include "shared_ptr.h"
+// CHECK-FIXES: #include <memory>
 
 struct Base {
   Base();
diff --git a/test/clang-tidy/modernize-make-unique-header.cpp b/test/clang-tidy/modernize-make-unique-header.cpp
new file mode 100644
index 0000000..e6c2a61
--- /dev/null
+++ b/test/clang-tidy/modernize-make-unique-header.cpp
@@ -0,0 +1,17 @@
+// RUN: %check_clang_tidy %s modernize-make-unique %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN:     [{key: modernize-make-unique.MakeSmartPtrFunction, \
+// RUN:       value: 'my::MakeUnique'}, \
+// RUN:      {key: modernize-make-unique.MakeSmartPtrFunctionHeader, \
+// RUN:       value: 'make_unique_util.h'} \
+// RUN:     ]}" \
+// RUN:   -- -std=c++11 -I%S/Inputs/modernize-smart-ptr
+
+#include "unique_ptr.h"
+// CHECK-FIXES: #include "make_unique_util.h"
+
+void f() {
+  std::unique_ptr<int> P1 = std::unique_ptr<int>(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use my::MakeUnique instead
+  // CHECK-FIXES: std::unique_ptr<int> P1 = my::MakeUnique<int>();
+}
diff --git a/test/clang-tidy/modernize-make-unique-macros.cpp b/test/clang-tidy/modernize-make-unique-macros.cpp
new file mode 100644
index 0000000..e3e5479
--- /dev/null
+++ b/test/clang-tidy/modernize-make-unique-macros.cpp
@@ -0,0 +1,28 @@
+// RUN: %check_clang_tidy %s modernize-make-unique %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-make-unique.IgnoreMacros, value: 0}]}" \
+// RUN:   -- -std=c++11  -I%S/Inputs/modernize-smart-ptr
+
+#include "unique_ptr.h"
+
+class Foo {};
+class Bar {};
+#define DEFINE(...) __VA_ARGS__
+// CHECK-FIXES: {{^}}#define DEFINE(...) __VA_ARGS__{{$}}
+template<typename T>
+void g2(std::unique_ptr<Foo> *t) {
+  DEFINE(
+  // CHECK-FIXES: {{^ *}}DEFINE({{$}}
+      auto p = std::unique_ptr<Foo>(new Foo);
+      // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use std::make_unique instead
+      // CHECK-FIXES: {{^ *}}auto p = std::unique_ptr<Foo>(new Foo);{{$}}
+      t->reset(new Foo);
+      // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use std::make_unique instead
+      // CHECK-FIXES: {{^ *}}t->reset(new Foo);{{$}}
+      );
+      // CHECK-FIXES: {{^ *}});{{$}}
+}
+void macro() {
+  std::unique_ptr<Foo> *t;
+  g2<Bar>(t);
+}
+#undef DEFINE
diff --git a/test/clang-tidy/modernize-make-unique.cpp b/test/clang-tidy/modernize-make-unique.cpp
index 268c46b..06f0905 100644
--- a/test/clang-tidy/modernize-make-unique.cpp
+++ b/test/clang-tidy/modernize-make-unique.cpp
@@ -1,31 +1,9 @@
-// RUN: %check_clang_tidy %s modernize-make-unique %t
+// RUN: %check_clang_tidy %s modernize-make-unique %t -- -- -std=c++11 \
+// RUN:   -I%S/Inputs/modernize-smart-ptr
 
-namespace std {
-
-template <typename T>
-class default_delete {};
-
-template <typename type, typename Deleter = std::default_delete<type>>
-class unique_ptr {
-public:
-  unique_ptr();
-  unique_ptr(type *ptr);
-  unique_ptr(const unique_ptr<type> &t) = delete;
-  unique_ptr(unique_ptr<type> &&t);
-  ~unique_ptr();
-  type &operator*() { return *ptr; }
-  type *operator->() { return ptr; }
-  type *release();
-  void reset();
-  void reset(type *pt);
-  unique_ptr &operator=(unique_ptr &&);
-  template <typename T>
-  unique_ptr &operator=(unique_ptr<T> &&);
-
-private:
-  type *ptr;
-};
-}
+#include "unique_ptr.h"
+#include "initializer_list.h"
+// CHECK-FIXES: #include <memory>
 
 struct Base {
   Base();
@@ -49,6 +27,38 @@
 
 struct Empty {};
 
+struct E {
+  E(std::initializer_list<int>);
+  E();
+};
+
+struct F {
+  F(std::initializer_list<int>);
+  F();
+  int a;
+};
+
+struct G {
+  G(std::initializer_list<int>);
+  G(int);
+};
+
+struct H {
+  H(std::vector<int>);
+};
+
+struct I {
+  I(G);
+};
+
+namespace {
+class Foo {};
+} // namespace
+
+namespace bar {
+class Bar {};
+} // namespace bar
+
 template <class T>
 using unique_ptr_ = std::unique_ptr<T>;
 
@@ -239,6 +249,138 @@
   std::unique_ptr<Empty> PEmpty = std::unique_ptr<Empty>(new Empty{});
   // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use std::make_unique instead
   // CHECK-FIXES: std::unique_ptr<Empty> PEmpty = std::make_unique<Empty>(Empty{});
+
+  // Initialization with default constructor.
+  std::unique_ptr<E> PE1 = std::unique_ptr<E>(new E{});
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<E> PE1 = std::make_unique<E>();
+  PE1.reset(new E{});
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+  // CHECK-FIXES: PE1 = std::make_unique<E>();
+
+  //============================================================================
+  //  NOTE: For initlializer-list constructors, the check only gives warnings,
+  //  and no fixes are generated.
+  //============================================================================
+
+  // Initialization with the initializer-list constructor.
+  std::unique_ptr<E> PE2 = std::unique_ptr<E>(new E{1, 2});
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<E> PE2 = std::unique_ptr<E>(new E{1, 2});
+  PE2.reset(new E{1, 2});
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+  // CHECK-FIXES: PE2.reset(new E{1, 2});
+
+  // Initialization with default constructor.
+  std::unique_ptr<F> PF1 = std::unique_ptr<F>(new F());
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<F> PF1 = std::make_unique<F>();
+  PF1.reset(new F());
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+  // CHECK-FIXES: PF1 = std::make_unique<F>();
+
+  // Initialization with default constructor.
+  std::unique_ptr<F> PF2 = std::unique_ptr<F>(new F{});
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<F> PF2 = std::make_unique<F>();
+  PF2.reset(new F());
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+  // CHECK-FIXES: PF2 = std::make_unique<F>();
+
+  // Initialization with the initializer-list constructor.
+  std::unique_ptr<F> PF3 = std::unique_ptr<F>(new F{1});
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<F> PF3 = std::unique_ptr<F>(new F{1});
+  PF3.reset(new F{1});
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+  // CHECK-FIXES: PF3.reset(new F{1});
+
+  // Initialization with the initializer-list constructor.
+  std::unique_ptr<F> PF4 = std::unique_ptr<F>(new F{1, 2});
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<F> PF4 = std::unique_ptr<F>(new F{1, 2});
+
+  // Initialization with the initializer-list constructor.
+  std::unique_ptr<F> PF5 = std::unique_ptr<F>(new F({1, 2}));
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<F> PF5 = std::unique_ptr<F>(new F({1, 2}));
+
+  // Initialization with the initializer-list constructor as the default
+  // constructor is not present.
+  std::unique_ptr<G> PG1 = std::unique_ptr<G>(new G{});
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<G> PG1 = std::unique_ptr<G>(new G{});
+  PG1.reset(new G{});
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+  // CHECK-FIXES: PG1.reset(new G{});
+
+  // Initialization with the initializer-list constructor.
+  std::unique_ptr<G> PG2 = std::unique_ptr<G>(new G{1});
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<G> PG2 = std::unique_ptr<G>(new G{1});
+
+  // Initialization with the initializer-list constructor.
+  std::unique_ptr<G> PG3 = std::unique_ptr<G>(new G{1, 2});
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<G> PG3 = std::unique_ptr<G>(new G{1, 2});
+
+  std::unique_ptr<H> PH1 = std::unique_ptr<H>(new H({1, 2, 3}));
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<H> PH1 = std::unique_ptr<H>(new H({1, 2, 3}));
+  PH1.reset(new H({1, 2, 3}));
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+  // CHECK-FIXES: PH1.reset(new H({1, 2, 3}));
+
+  std::unique_ptr<I> PI1 = std::unique_ptr<I>(new I(G({1, 2, 3})));
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr<I> PI1 = std::make_unique<I>(G({1, 2, 3}));
+  PI1.reset(new I(G({1, 2, 3})));
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use std::make_unique instead
+  // CHECK-FIXES: PI1 = std::make_unique<I>(G({1, 2, 3}));
+
+  std::unique_ptr<Foo> FF = std::unique_ptr<Foo>(new Foo());
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning:
+  // CHECK-FIXES: std::unique_ptr<Foo> FF = std::make_unique<Foo>();
+  FF.reset(new Foo());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning:
+  // CHECK-FIXES: FF = std::make_unique<Foo>();
+
+  std::unique_ptr<bar::Bar> BB = std::unique_ptr<bar::Bar>(new bar::Bar());
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning:
+  // CHECK-FIXES: std::unique_ptr<bar::Bar> BB = std::make_unique<bar::Bar>();
+  BB.reset(new bar::Bar());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning:
+  // CHECK-FIXES: BB = std::make_unique<bar::Bar>();
+
+  std::unique_ptr<Foo[]> FFs;
+  FFs.reset(new Foo[5]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning:
+  // CHECK-FIXES: FFs = std::make_unique<Foo[]>(5);
+  FFs.reset(new Foo[5]());
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning:
+  // CHECK-FIXES: FFs = std::make_unique<Foo[]>(5);
+  const int Num = 1;
+  FFs.reset(new Foo[Num]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning:
+  // CHECK-FIXES: FFs = std::make_unique<Foo[]>(Num);
+  int Num2 = 1;
+  FFs.reset(new Foo[Num2]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning:
+  // CHECK-FIXES: FFs = std::make_unique<Foo[]>(Num2);
+
+  std::unique_ptr<int[]> FI;
+  FI.reset(new int[5]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning:
+  // CHECK-FIXES: FI = std::make_unique<int[]>(5);
+  FI.reset(new int[5]());
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning:
+  // CHECK-FIXES: FI = std::make_unique<int[]>(5);
+  FI.reset(new int[Num]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning:
+  // CHECK-FIXES: FI = std::make_unique<int[]>(Num);
+  FI.reset(new int[Num2]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning:
+  // CHECK-FIXES: FI = std::make_unique<int[]>(Num2);
 }
 
 void aliases() {
@@ -307,3 +449,39 @@
   // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_unique instead
   // CHECK-FIXES: *Q = std::make_unique<int>();
 }
+
+#define DEFINE(...) __VA_ARGS__
+template<typename T>
+void g2(std::unique_ptr<Foo> *t) {
+  DEFINE(auto p = std::unique_ptr<Foo>(new Foo); t->reset(new Foo););
+}
+void macro() {
+  std::unique_ptr<Foo> *t;
+  g2<bar::Bar>(t);
+}
+#undef DEFINE
+
+class UniqueFoo : public std::unique_ptr<Foo> {
+ public:
+  void foo() {
+    reset(new Foo);
+    this->reset(new Foo);
+    // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use std::make_unique instead
+    // CHECK-FIXES: *this = std::make_unique<Foo>();
+    (*this).reset(new Foo);
+    // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead
+    // CHECK-FIXES: (*this) = std::make_unique<Foo>();
+  }
+};
+
+// Ignore statements inside a template instantiation.
+template<typename T>
+void template_fun(T* t) {
+  std::unique_ptr<T> t2 = std::unique_ptr<T>(new T);
+  t2.reset(new T);
+}
+
+void invoke_template() {
+  Foo* foo;
+  template_fun(foo);
+}
diff --git a/test/clang-tidy/modernize-unary-static-assert.cpp b/test/clang-tidy/modernize-unary-static-assert.cpp
new file mode 100644
index 0000000..fd39d5b
--- /dev/null
+++ b/test/clang-tidy/modernize-unary-static-assert.cpp
@@ -0,0 +1,25 @@
+// RUN: %check_clang_tidy %s modernize-unary-static-assert %t -- -- -std=c++1z
+
+#define FOO static_assert(sizeof(a) <= 15, "");
+#define MSG ""
+
+void f_textless(int a) {
+  static_assert(sizeof(a) <= 10, "");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use unary 'static_assert' when the string literal is an empty string [modernize-unary-static-assert]
+  // CHECK-FIXES: {{^}}  static_assert(sizeof(a) <= 10 );{{$}}
+  static_assert(sizeof(a) <= 12, L"");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use unary 'static_assert' when
+  // CHECK-FIXES: {{^}}  static_assert(sizeof(a) <= 12 );{{$}}
+  FOO
+  // CHECK-FIXES: {{^}}  FOO{{$}}
+  static_assert(sizeof(a) <= 17, MSG);
+  // CHECK-FIXES: {{^}}  static_assert(sizeof(a) <= 17, MSG);{{$}}
+}
+
+void f_with_tex(int a) {
+  static_assert(sizeof(a) <= 10, "Size of variable a is out of range!");
+}
+
+void f_unary(int a) { static_assert(sizeof(a) <= 10); }
+
+void f_incorrect_assert() { static_assert(""); }
diff --git a/test/clang-tidy/modernize-use-bool-literals-ignore-macros.cpp b/test/clang-tidy/modernize-use-bool-literals-ignore-macros.cpp
new file mode 100644
index 0000000..cf8f72c
--- /dev/null
+++ b/test/clang-tidy/modernize-use-bool-literals-ignore-macros.cpp
@@ -0,0 +1,148 @@
+// RUN: %check_clang_tidy %s modernize-use-bool-literals %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN:             [{key: modernize-use-bool-literals.IgnoreMacros, \
+// RUN:               value: 1}]}" \
+// RUN:   -- -std=c++11
+
+bool IntToTrue = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: converting integer literal to bool, use bool literal instead [modernize-use-bool-literals]
+// CHECK-FIXES: {{^}}bool IntToTrue = true;{{$}}
+
+bool IntToFalse(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool IntToFalse(false);{{$}}
+
+bool LongLongToTrue{0x1LL};
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool LongLongToTrue{true};{{$}}
+
+bool ExplicitCStyleIntToFalse = (bool)0;
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool ExplicitCStyleIntToFalse = false;{{$}}
+
+bool ExplicitFunctionalIntToFalse = bool(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool ExplicitFunctionalIntToFalse = false;{{$}}
+
+bool ExplicitStaticIntToFalse = static_cast<bool>(0);
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: converting integer literal to bool
+// CHECK-FIXES: {{^}}bool ExplicitStaticIntToFalse = false;{{$}}
+
+#define TRUE_MACRO 1
+// CHECK-FIXES: {{^}}#define TRUE_MACRO 1{{$}}
+
+bool MacroIntToTrue = TRUE_MACRO;
+// CHECK-FIXES: {{^}}bool MacroIntToTrue = TRUE_MACRO;{{$}}
+
+#define FALSE_MACRO bool(0)
+// CHECK-FIXES: {{^}}#define FALSE_MACRO bool(0){{$}}
+
+bool TrueBool = true; // OK
+
+bool FalseBool = bool(FALSE_MACRO);
+// CHECK-FIXES: {{^}}bool FalseBool = bool(FALSE_MACRO);{{$}}
+
+void boolFunction(bool bar) {
+
+}
+
+char Character = 0; // OK
+
+unsigned long long LongInteger = 1; // OK
+
+#define MACRO_DEPENDENT_CAST(x) static_cast<bool>(x)
+// CHECK-FIXES: {{^}}#define MACRO_DEPENDENT_CAST(x) static_cast<bool>(x){{$}}
+
+bool MacroDependentBool = MACRO_DEPENDENT_CAST(0);
+// CHECK-FIXES: {{^}}bool MacroDependentBool = MACRO_DEPENDENT_CAST(0);{{$}}
+
+bool ManyMacrosDependent = MACRO_DEPENDENT_CAST(FALSE_MACRO);
+// CHECK-FIXES: {{^}}bool ManyMacrosDependent = MACRO_DEPENDENT_CAST(FALSE_MACRO);{{$}}
+
+class FooClass {
+  public:
+  FooClass() : JustBool(0) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}FooClass() : JustBool(false) {}{{$}}
+  FooClass(int) : JustBool{0} {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}FooClass(int) : JustBool{false} {}{{$}}
+  private:
+  bool JustBool;
+  bool BoolWithBraces{0};
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}bool BoolWithBraces{false};{{$}}
+  bool BoolFromInt = 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}bool BoolFromInt = false;{{$}}
+  bool SimpleBool = true; // OK
+};
+
+template<typename type>
+void templateFunction(type) {
+  type TemplateType = 0;
+  // CHECK-FIXES: {{^ *}}type TemplateType = 0;{{$}}
+}
+
+template<int c>
+void valueDependentTemplateFunction() {
+  bool Boolean = c;
+  // CHECK-FIXES: {{^ *}}bool Boolean = c;{{$}}
+}
+
+template<typename type>
+void anotherTemplateFunction(type) {
+  bool JustBool = 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}bool JustBool = false;{{$}}
+}
+
+int main() {
+  boolFunction(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}boolFunction(true);{{$}}
+
+  boolFunction(false);
+
+  templateFunction(0);
+
+  templateFunction(false);
+
+  valueDependentTemplateFunction<1>();
+
+  anotherTemplateFunction(1);
+
+  IntToTrue = 1;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}IntToTrue = true;{{$}}
+}
+
+static int Value = 1;
+
+bool Function1() {
+  bool Result = Value == 1 ? 1 : 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: converting integer literal to bool
+  // CHECK-MESSAGES: :[[@LINE-2]]:34: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}bool Result = Value == 1 ? true : false;{{$}}
+  return Result;
+}
+
+bool Function2() {
+  return Value == 1 ? 1 : 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: converting integer literal to bool
+  // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}return Value == 1 ? true : false;{{$}}
+}
+
+void foo() {
+  bool Result;
+  Result = Value == 1 ? true : 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}Result = Value == 1 ? true : false;{{$}}
+  Result = Value == 1 ? false : bool(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}Result = Value == 1 ? false : false;{{$}}
+  Result = Value == 1 ? (bool)0 : false;
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: converting integer literal to bool
+  // CHECK-FIXES: {{^ *}}Result = Value == 1 ? false : false;{{$}}
+}
diff --git a/test/clang-tidy/modernize-use-bool-literals.cpp b/test/clang-tidy/modernize-use-bool-literals.cpp
index 35c3ec4..f2ab9ce 100644
--- a/test/clang-tidy/modernize-use-bool-literals.cpp
+++ b/test/clang-tidy/modernize-use-bool-literals.cpp
@@ -1,4 +1,8 @@
-// RUN: %check_clang_tidy %s modernize-use-bool-literals %t
+// RUN: %check_clang_tidy %s modernize-use-bool-literals %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN:             [{key: modernize-use-bool-literals.IgnoreMacros, \
+// RUN:               value: 0}]}" \
+// RUN:   -- -std=c++11
 
 bool IntToTrue = 1;
 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: converting integer literal to bool, use bool literal instead [modernize-use-bool-literals]
diff --git a/test/clang-tidy/modernize-use-default-member-init.cpp b/test/clang-tidy/modernize-use-default-member-init.cpp
index 5b9b93c..0ed65df 100644
--- a/test/clang-tidy/modernize-use-default-member-init.cpp
+++ b/test/clang-tidy/modernize-use-default-member-init.cpp
@@ -173,6 +173,16 @@
   // CHECK-FIXES: const char *s{"foo"};
 };
 
+struct PositiveStruct {
+  PositiveStruct() : s(7) {}
+  // CHECK-FIXES: PositiveStruct()  {}
+  struct {
+    int s;
+    // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use default member initializer for 's'
+    // CHECK-FIXES: int s{7};
+  };
+};
+
 template <typename T>
 struct NegativeTemplate {
     NegativeTemplate() : t() {}
diff --git a/test/clang-tidy/modernize-use-emplace-ignore-implicit-constructors.cpp b/test/clang-tidy/modernize-use-emplace-ignore-implicit-constructors.cpp
new file mode 100644
index 0000000..2f6b37f
--- /dev/null
+++ b/test/clang-tidy/modernize-use-emplace-ignore-implicit-constructors.cpp
@@ -0,0 +1,123 @@
+// RUN: %check_clang_tidy %s modernize-use-emplace %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN:             [{key: modernize-use-emplace.IgnoreImplicitConstructors, \
+// RUN:               value: 1}] \
+// RUN:             }" -- -std=c++11
+
+namespace std {
+template <typename>
+class initializer_list
+{
+public:
+  initializer_list() noexcept {}
+};
+
+template <typename T>
+class vector {
+public:
+  vector() = default;
+  vector(initializer_list<T>) {}
+
+  void push_back(const T &) {}
+  void push_back(T &&) {}
+
+  template <typename... Args>
+  void emplace_back(Args &&... args){};
+  ~vector();
+};
+
+} // namespace std
+
+void testInts() {
+  std::vector<int> v;
+  v.push_back(42);
+  v.push_back(int(42));
+  v.push_back(int{42});
+  v.push_back(42.0);
+  int z;
+  v.push_back(z);
+}
+
+struct Something {
+  Something(int a, int b = 41) {}
+  Something() {}
+  void push_back(Something);
+  int getInt() { return 42; }
+};
+
+struct Convertable {
+  operator Something() { return Something{}; }
+};
+
+struct Zoz {
+  Zoz(Something, int = 42) {}
+};
+
+Zoz getZoz(Something s) { return Zoz(s); }
+
+void test_Something() {
+  std::vector<Something> v;
+
+  v.push_back(Something(1, 2));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back instead of push_back [modernize-use-emplace]
+  // CHECK-FIXES: v.emplace_back(1, 2);
+
+  v.push_back(Something{1, 2});
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(1, 2);
+
+  v.push_back(Something());
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back();
+
+  v.push_back(Something{});
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back();
+
+  Something Different;
+  v.push_back(Something(Different.getInt(), 42));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(Different.getInt(), 42);
+
+  v.push_back(Different.getInt());
+  v.push_back(42);
+
+  Something temporary(42, 42);
+  temporary.push_back(temporary);
+  v.push_back(temporary);
+
+  v.push_back(Convertable());
+  v.push_back(Convertable{});
+  Convertable s;
+  v.push_back(s);
+}
+
+template <typename ElemType>
+void dependOnElem() {
+  std::vector<ElemType> v;
+  v.push_back(ElemType(42));
+}
+
+template <typename ContainerType>
+void dependOnContainer() {
+  ContainerType v;
+  v.push_back(Something(42));
+}
+
+void callDependent() {
+  dependOnElem<Something>();
+  dependOnContainer<std::vector<Something>>();
+}
+
+void test2() {
+  std::vector<Zoz> v;
+  v.push_back(Zoz(Something(21, 37)));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(Something(21, 37));
+
+  v.push_back(Zoz(Something(21, 37), 42));
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
+  // CHECK-FIXES: v.emplace_back(Something(21, 37), 42);
+
+  v.push_back(getZoz(Something(1, 2)));
+}
diff --git a/test/clang-tidy/modernize-use-equals-default-copy.cpp b/test/clang-tidy/modernize-use-equals-default-copy.cpp
index df21cc0..26f35af 100644
--- a/test/clang-tidy/modernize-use-equals-default-copy.cpp
+++ b/test/clang-tidy/modernize-use-equals-default-copy.cpp
@@ -1,4 +1,6 @@
-// RUN: %check_clang_tidy %s modernize-use-equals-default %t -- -- -std=c++11 -fno-delayed-template-parsing -fexceptions
+// RUN: %check_clang_tidy %s modernize-use-equals-default %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-use-equals-default.IgnoreMacros, value: 0}]}" \
+// RUN:   -- -std=c++11 -fno-delayed-template-parsing -fexceptions
 
 // Out of line definition.
 struct OL {
diff --git a/test/clang-tidy/modernize-use-equals-default-macros.cpp b/test/clang-tidy/modernize-use-equals-default-macros.cpp
new file mode 100644
index 0000000..2277a86
--- /dev/null
+++ b/test/clang-tidy/modernize-use-equals-default-macros.cpp
@@ -0,0 +1,13 @@
+// RUN: %check_clang_tidy %s modernize-use-equals-default %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-use-equals-default.IgnoreMacros, value: 0}]}" \
+// RUN:   -- -std=c++11
+
+#define STRUCT_WITH_DEFAULT(_base, _type) \
+  struct _type {                          \
+    _type() {}                            \
+    _base value;                          \
+  };
+
+STRUCT_WITH_DEFAULT(unsigned char, InMacro)
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use '= default' to define a trivial default constructor
+// CHECK-MESSAGES: :[[@LINE-6]]:13: note:
diff --git a/test/clang-tidy/modernize-use-equals-default.cpp b/test/clang-tidy/modernize-use-equals-default.cpp
index 4892e58..8fa15ff 100644
--- a/test/clang-tidy/modernize-use-equals-default.cpp
+++ b/test/clang-tidy/modernize-use-equals-default.cpp
@@ -204,6 +204,4 @@
     _base value;                          \
   };
 
-STRUCT_WITH_DEFAULT(unsigned char, Hex8Default)
-// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use '= default' to define a trivial default constructor
-// CHECK-MESSAGES: :[[@LINE-6]]:13: note:
+STRUCT_WITH_DEFAULT(unsigned char, InMacro)
diff --git a/test/clang-tidy/modernize-use-nullptr.cpp b/test/clang-tidy/modernize-use-nullptr.cpp
index 7e1eb14..878c114 100644
--- a/test/clang-tidy/modernize-use-nullptr.cpp
+++ b/test/clang-tidy/modernize-use-nullptr.cpp
@@ -261,3 +261,45 @@
 void IgnoreSubstTemplateType() {
   TemplateClass<int*> a(1);
 }
+
+// Test on casting nullptr.
+struct G {
+  explicit G(bool, const char * = NULL) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use nullptr
+  // CHECK-FIXES: explicit G(bool, const char * = nullptr) {}
+};
+bool g(const char*);
+void test_cast_nullptr() {
+  G(g(nullptr));
+  G(g((nullptr)));
+  G(g(static_cast<char*>(nullptr)));
+  G(g(static_cast<const char*>(nullptr)));
+}
+
+// Test on recognizing multiple NULLs.
+class H {
+public:
+  H(bool);
+};
+
+#define T(expression) H(expression);
+bool h(int *, int *, int * = nullptr);
+void test_multiple_nulls() {
+  T(h(NULL, NULL));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use nullptr
+// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: use nullptr
+// CHECK-FIXES: T(h(nullptr, nullptr));
+  T(h(NULL, nullptr));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use nullptr
+// CHECK-FIXES: T(h(nullptr, nullptr));
+  T(h(nullptr, NULL));
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
+// CHECK-FIXES: T(h(nullptr, nullptr));
+  T(h(nullptr, nullptr));
+  T(h(NULL, NULL, NULL));
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use nullptr
+// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: use nullptr
+// CHECK-MESSAGES: :[[@LINE-3]]:19: warning: use nullptr
+// CHECK-FIXES: T(h(nullptr, nullptr, nullptr));
+}
+#undef T
diff --git a/test/clang-tidy/modernize-use-override.cpp b/test/clang-tidy/modernize-use-override.cpp
index 263290f..24aafe5 100644
--- a/test/clang-tidy/modernize-use-override.cpp
+++ b/test/clang-tidy/modernize-use-override.cpp
@@ -12,6 +12,10 @@
 
 struct MUST_USE_RESULT MustUseResultObject {};
 
+struct IntPair {
+  int First, Second;
+};
+
 struct Base {
   virtual ~Base() {}
   virtual void a();
@@ -41,6 +45,8 @@
 
   virtual void ne() noexcept(false);
   virtual void t() throw();
+
+  virtual void il(IntPair);
 };
 
 struct SimpleCases : public Base {
@@ -221,6 +227,14 @@
   // CHECK-FIXES: {{^}}  void cv2() const volatile override // some comment
 };
 
+struct DefaultArguments : public Base {
+  // Tests for default arguments (with initializer lists).
+  // Make sure the override fix is placed after the argument list.
+  void il(IntPair p = {1, (2 + (3))}) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: annotate this
+  // CHECK-FIXES: {{^}}  void il(IntPair p = {1, (2 + (3))}) override {}
+};
+
 struct Macros : public Base {
   // Tests for 'virtual' and 'override' being defined through macros. Basically
   // give up for now.
diff --git a/test/clang-tidy/nonstandard-file-extension.test b/test/clang-tidy/nonstandard-file-extension.test
new file mode 100644
index 0000000..4cb4d11
--- /dev/null
+++ b/test/clang-tidy/nonstandard-file-extension.test
@@ -0,0 +1,6 @@
+// RUN: %check_clang_tidy -assume-filename=const-cast.cpp %s cppcoreguidelines-pro-type-const-cast %t
+
+const int *i;
+int *j;
+void f() { j = const_cast<int *>(i); }
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: do not use const_cast [cppcoreguidelines-pro-type-const-cast]
diff --git a/test/clang-tidy/performance-implicit-cast-in-loop.cpp b/test/clang-tidy/performance-implicit-conversion-in-loop.cpp
similarity index 90%
rename from test/clang-tidy/performance-implicit-cast-in-loop.cpp
rename to test/clang-tidy/performance-implicit-conversion-in-loop.cpp
index 788debe..7b1ad39 100644
--- a/test/clang-tidy/performance-implicit-cast-in-loop.cpp
+++ b/test/clang-tidy/performance-implicit-conversion-in-loop.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s performance-implicit-cast-in-loop %t
+// RUN: %check_clang_tidy %s performance-implicit-conversion-in-loop %t
 
 // ---------- Classes used in the tests ----------
 
@@ -26,8 +26,8 @@
   T end();
 };
 
-// With this class, the implicit cast is a call to the (implicit) constructor of
-// the class.
+// With this class, the implicit conversion is a call to the (implicit)
+// constructor of the class.
 template <typename T>
 class ImplicitWrapper {
  public:
@@ -35,8 +35,8 @@
   ImplicitWrapper(const T& t);
 };
 
-// With this class, the implicit cast is a call to the conversion operators of
-// SimpleClass and ComplexClass.
+// With this class, the implicit conversion is a call to the conversion
+// operators of SimpleClass and ComplexClass.
 template <typename T>
 class OperatorWrapper {
  public:
@@ -98,7 +98,7 @@
 
 void ImplicitSimpleClassIterator() {
   for (const ImplicitWrapper<SimpleClass>& foo : SimpleView()) {}
-  // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the loop variable 'foo' is different from the one returned by the iterator and generates an implicit cast; you can either change the type to the correct one ('const SimpleClass &' but 'const auto&' is always a valid option) or remove the reference to make it explicit that you are creating a new value [performance-implicit-cast-in-loop]
+  // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the loop variable 'foo' is different from the one returned by the iterator and generates an implicit conversion; you can either change the type to the matching one ('const SimpleClass &' but 'const auto&' is always a valid option) or remove the reference to make it explicit that you are creating a new value [performance-implicit-conversion-in-loop]
   // for (ImplicitWrapper<SimpleClass>& foo : SimpleView()) {}
   for (const ImplicitWrapper<SimpleClass> foo : SimpleView()) {}
   for (ImplicitWrapper<SimpleClass>foo : SimpleView()) {}
diff --git a/test/clang-tidy/performance-inefficient-string-concatenation.cpp b/test/clang-tidy/performance-inefficient-string-concatenation.cpp
index f4b293a..1dbd56b 100644
--- a/test/clang-tidy/performance-inefficient-string-concatenation.cpp
+++ b/test/clang-tidy/performance-inefficient-string-concatenation.cpp
@@ -19,6 +19,8 @@
 int main() {
   std::string mystr1, mystr2;
   std::wstring mywstr1, mywstr2;
+  auto myautostr1 = mystr1;
+  auto myautostr2 = mystr2;
 
   for (int i = 0; i < 10; ++i) {
     f(mystr1 + mystr2 + mystr1);
@@ -33,6 +35,8 @@
     // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: string concatenation
     mywstr1 = mywstr2 + mywstr2 + mywstr2;
     // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: string concatenation
+    myautostr1 = myautostr1 + myautostr2;
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: string concatenation
 
     mywstr1 = mywstr2 + mywstr2;
     mystr1 = mystr2 + mystr2;
diff --git a/test/clang-tidy/performance-unnecessary-value-param-header.cpp b/test/clang-tidy/performance-unnecessary-value-param-header.cpp
new file mode 100644
index 0000000..9e4c246
--- /dev/null
+++ b/test/clang-tidy/performance-unnecessary-value-param-header.cpp
@@ -0,0 +1,20 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: cp %S/Inputs/performance-unnecessary-value-param/header.h %t/header.h
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t/temp -- -- -std=c++11 -I %t
+// RUN: diff %t/header.h %S/Inputs/performance-unnecessary-value-param/header-fixed.h
+
+#include "header.h"
+
+
+
+int f1(int n, ABC v1, ABC v2) {
+  // CHECK-MESSAGES: [[@LINE-1]]:19: warning: the parameter 'v1' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]
+  // CHECK-MESSAGES: [[@LINE-2]]:27: warning: the parameter 'v2' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]
+  // CHECK-FIXES: int f1(int n, const ABC& v1, const ABC& v2) {
+  return v1.get(n) + v2.get(n);
+}
+int f2(int n, ABC v2) {
+  // CHECK-MESSAGES: [[@LINE-1]]:19: warning: the parameter 'v2' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]
+  // CHECK-FIXES: int f2(int n, const ABC& v2) {
+}
diff --git a/test/clang-tidy/performance-unnecessary-value-param.cpp b/test/clang-tidy/performance-unnecessary-value-param.cpp
index 5491cbb..dcf82df 100644
--- a/test/clang-tidy/performance-unnecessary-value-param.cpp
+++ b/test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -348,3 +348,14 @@
   ExpensiveToCopyType E;
   NegativeUsingConstructor S(E);
 }
+
+template<typename T>
+void templateFunction(T) {
+}
+
+template<>
+void templateFunction<ExpensiveToCopyType>(ExpensiveToCopyType E) {
+  // CHECK-MESSAGES: [[@LINE-1]]:64: warning: the parameter 'E' is copied
+  // CHECK-FIXES: void templateFunction<ExpensiveToCopyType>(ExpensiveToCopyType E) {
+  E.constReference();
+}
diff --git a/test/clang-tidy/readability-braces-around-statements.cpp b/test/clang-tidy/readability-braces-around-statements.cpp
index 9730735..8dc5bf1 100644
--- a/test/clang-tidy/readability-braces-around-statements.cpp
+++ b/test/clang-tidy/readability-braces-around-statements.cpp
@@ -176,12 +176,13 @@
   if (!p)
     f("\
 ");
-  // CHECK-MESSAGES: :[[@LINE-3]]:10: warning: statement should be inside braces
-  // CHECK-FIXES:      {{^  }}if (!p) {{{$}}
-  // CHECK-FIXES-NEXT: {{^    }}f("\{{$}}
-  // CHECK-FIXES-_NEXT: {{^}}");{{$}} FIXME: This breaks (http://llvm.org/PR26228)
-  // CHECK-FIXES-_NEXT: {{^}}}{{$}}
-}
+} // end of f
+// CHECK-MESSAGES: :[[@LINE-4]]:10: warning: statement should be inside braces
+// CHECK-FIXES:      {{^}}  if (!p) {{{$}}
+// CHECK-FIXES-NEXT: {{^}}    f("\{{$}}
+// CHECK-FIXES-NEXT: {{^}}");{{$}}
+// CHECK-FIXES-NEXT: {{^}}}{{$}}
+// CHECK-FIXES-NEXT: {{^}}} // end of f{{$}}
 
 #define M(x) x
 
diff --git a/test/clang-tidy/readability-implicit-bool-cast-cxx98.cpp b/test/clang-tidy/readability-implicit-bool-cast-cxx98.cpp
deleted file mode 100644
index 791c7a1..0000000
--- a/test/clang-tidy/readability-implicit-bool-cast-cxx98.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-// RUN: %check_clang_tidy %s readability-implicit-bool-cast %t -- -- -std=c++98
-
-// We need NULL macro, but some buildbots don't like including <cstddef> header
-// This is a portable way of getting it to work
-#undef NULL
-#define NULL 0L
-
-template<typename T>
-void functionTaking(T);
-
-struct Struct {
-  int member;
-};
-
-void useOldNullMacroInReplacements() {
-  int* pointer = NULL;
-  functionTaking<bool>(pointer);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int *' -> bool [readability-implicit-bool-cast]
-  // CHECK-FIXES: functionTaking<bool>(pointer != 0);
-
-  int Struct::* memberPointer = NULL;
-  functionTaking<bool>(!memberPointer);
-  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit cast 'int Struct::*' -> bool
-  // CHECK-FIXES: functionTaking<bool>(memberPointer == 0);
-}
-
-void fixFalseLiteralConvertingToNullPointer() {
-  functionTaking<int*>(false);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast bool -> 'int *'
-  // CHECK-FIXES: functionTaking<int*>(0);
-
-  int* pointer = NULL;
-  if (pointer == false) {}
-  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: implicit cast bool -> 'int *'
-  // CHECK-FIXES: if (pointer == 0) {}
-
-  functionTaking<int Struct::*>(false);
-  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit cast bool -> 'int Struct::*'
-  // CHECK-FIXES: functionTaking<int Struct::*>(0);
-
-  int Struct::* memberPointer = NULL;
-  if (memberPointer != false) {}
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast bool -> 'int Struct::*'
-  // CHECK-FIXES: if (memberPointer != 0) {}
-}
diff --git a/test/clang-tidy/readability-implicit-bool-cast.cpp b/test/clang-tidy/readability-implicit-bool-cast.cpp
deleted file mode 100644
index 9e4aac7..0000000
--- a/test/clang-tidy/readability-implicit-bool-cast.cpp
+++ /dev/null
@@ -1,439 +0,0 @@
-// RUN: %check_clang_tidy %s readability-implicit-bool-cast %t
-
-// We need NULL macro, but some buildbots don't like including <cstddef> header
-// This is a portable way of getting it to work
-#undef NULL
-#define NULL 0L
-
-template<typename T>
-void functionTaking(T);
-
-struct Struct {
-  int member;
-};
-
-
-////////// Implicit cast from bool.
-
-void implicitCastFromBoolSimpleCases() {
-  bool boolean = true;
-
-  functionTaking<bool>(boolean);
-
-  functionTaking<int>(boolean);
-  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: implicit cast bool -> 'int' [readability-implicit-bool-cast]
-  // CHECK-FIXES: functionTaking<int>(static_cast<int>(boolean));
-
-  functionTaking<unsigned long>(boolean);
-  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit cast bool -> 'unsigned long'
-  // CHECK-FIXES: functionTaking<unsigned long>(static_cast<unsigned long>(boolean));
-
-  functionTaking<char>(boolean);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast bool -> 'char'
-  // CHECK-FIXES: functionTaking<char>(static_cast<char>(boolean));
-
-  functionTaking<float>(boolean);
-  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit cast bool -> 'float'
-  // CHECK-FIXES: functionTaking<float>(static_cast<float>(boolean));
-
-  functionTaking<double>(boolean);
-  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: implicit cast bool -> 'double'
-  // CHECK-FIXES: functionTaking<double>(static_cast<double>(boolean));
-}
-
-float implicitCastFromBoolInReturnValue() {
-  bool boolean = false;
-  return boolean;
-  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit cast bool -> 'float'
-  // CHECK-FIXES: return static_cast<float>(boolean);
-}
-
-void implicitCastFromBoolInSingleBoolExpressions(bool b1, bool b2) {
-  bool boolean = true;
-  boolean = b1 ^ b2;
-  boolean = b1 && b2;
-  boolean |= !b1 || !b2;
-  boolean &= b1;
-  boolean = b1 == true;
-  boolean = b2 != false;
-
-  int integer = boolean - 3;
-  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: implicit cast bool -> 'int'
-  // CHECK-FIXES: int integer = static_cast<int>(boolean) - 3;
-
-  float floating = boolean / 0.3f;
-  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: implicit cast bool -> 'float'
-  // CHECK-FIXES: float floating = static_cast<float>(boolean) / 0.3f;
-
-  char character = boolean;
-  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: implicit cast bool -> 'char'
-  // CHECK-FIXES: char character = static_cast<char>(boolean);
-}
-
-void implicitCastFromBoollInComplexBoolExpressions() {
-  bool boolean = true;
-  bool anotherBoolean = false;
-
-  int integer = boolean && anotherBoolean;
-  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: implicit cast bool -> 'int'
-  // CHECK-FIXES: int integer = static_cast<int>(boolean && anotherBoolean);
-
-  unsigned long unsignedLong = (! boolean) + 4ul;
-  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: implicit cast bool -> 'unsigned long'
-  // CHECK-FIXES: unsigned long unsignedLong = static_cast<unsigned long>(! boolean) + 4ul;
-
-  float floating = (boolean || anotherBoolean) * 0.3f;
-  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: implicit cast bool -> 'float'
-  // CHECK-FIXES: float floating = static_cast<float>(boolean || anotherBoolean) * 0.3f;
-
-  double doubleFloating = (boolean && (anotherBoolean || boolean)) * 0.3;
-  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: implicit cast bool -> 'double'
-  // CHECK-FIXES: double doubleFloating = static_cast<double>(boolean && (anotherBoolean || boolean)) * 0.3;
-}
-
-void implicitCastFromBoolLiterals() {
-  functionTaking<int>(true);
-  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: implicit cast bool -> 'int'
-  // CHECK-FIXES: functionTaking<int>(1);
-
-  functionTaking<unsigned long>(false);
-  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit cast bool -> 'unsigned long'
-  // CHECK-FIXES: functionTaking<unsigned long>(0u);
-
-  functionTaking<signed char>(true);
-  // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: implicit cast bool -> 'signed char'
-  // CHECK-FIXES: functionTaking<signed char>(1);
-
-  functionTaking<float>(false);
-  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit cast bool -> 'float'
-  // CHECK-FIXES: functionTaking<float>(0.0f);
-
-  functionTaking<double>(true);
-  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: implicit cast bool -> 'double'
-  // CHECK-FIXES: functionTaking<double>(1.0);
-}
-
-void implicitCastFromBoolInComparisons() {
-  bool boolean = true;
-  int integer = 0;
-
-  functionTaking<bool>(boolean == integer);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast bool -> 'int'
-  // CHECK-FIXES: functionTaking<bool>(static_cast<int>(boolean) == integer);
-
-  functionTaking<bool>(integer != boolean);
-  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: implicit cast bool -> 'int'
-  // CHECK-FIXES: functionTaking<bool>(integer != static_cast<int>(boolean));
-}
-
-void ignoreBoolComparisons() {
-  bool boolean = true;
-  bool anotherBoolean = false;
-
-  functionTaking<bool>(boolean == anotherBoolean);
-  functionTaking<bool>(boolean != anotherBoolean);
-}
-
-void ignoreExplicitCastsFromBool() {
-  bool boolean = true;
-
-  int integer = static_cast<int>(boolean) + 3;
-  float floating = static_cast<float>(boolean) * 0.3f;
-  char character = static_cast<char>(boolean);
-}
-
-void ignoreImplicitCastFromBoolInMacroExpansions() {
-  bool boolean = true;
-
-  #define CAST_FROM_BOOL_IN_MACRO_BODY boolean + 3
-  int integerFromMacroBody = CAST_FROM_BOOL_IN_MACRO_BODY;
-
-  #define CAST_FROM_BOOL_IN_MACRO_ARGUMENT(x) x + 3
-  int integerFromMacroArgument = CAST_FROM_BOOL_IN_MACRO_ARGUMENT(boolean);
-}
-
-namespace ignoreImplicitCastFromBoolInTemplateInstantiations {
-
-template<typename T>
-void templateFunction() {
-  bool boolean = true;
-  T uknownType = boolean + 3;
-}
-
-void useOfTemplateFunction() {
-  templateFunction<int>();
-}
-
-} // namespace ignoreImplicitCastFromBoolInTemplateInstantiations
-
-////////// Implicit cast to bool.
-
-void implicitCastToBoolSimpleCases() {
-  int integer = 10;
-  functionTaking<bool>(integer);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int' -> bool
-  // CHECK-FIXES: functionTaking<bool>(integer != 0);
-
-  unsigned long unsignedLong = 10;
-  functionTaking<bool>(unsignedLong);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'unsigned long' -> bool
-  // CHECK-FIXES: functionTaking<bool>(unsignedLong != 0u);
-
-  float floating = 0.0f;
-  functionTaking<bool>(floating);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'float' -> bool
-  // CHECK-FIXES: functionTaking<bool>(floating != 0.0f);
-
-  double doubleFloating = 1.0f;
-  functionTaking<bool>(doubleFloating);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'double' -> bool
-  // CHECK-FIXES: functionTaking<bool>(doubleFloating != 0.0);
-
-  signed char character = 'a';
-  functionTaking<bool>(character);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'signed char' -> bool
-  // CHECK-FIXES: functionTaking<bool>(character != 0);
-
-  int* pointer = nullptr;
-  functionTaking<bool>(pointer);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int *' -> bool
-  // CHECK-FIXES: functionTaking<bool>(pointer != nullptr);
-
-  auto pointerToMember = &Struct::member;
-  functionTaking<bool>(pointerToMember);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int Struct::*' -> bool
-  // CHECK-FIXES: functionTaking<bool>(pointerToMember != nullptr);
-}
-
-void implicitCastToBoolInSingleExpressions() {
-  int integer = 10;
-  bool boolComingFromInt = integer;
-  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: implicit cast 'int' -> bool
-  // CHECK-FIXES: bool boolComingFromInt = integer != 0;
-
-  float floating = 10.0f;
-  bool boolComingFromFloat = floating;
-  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: implicit cast 'float' -> bool
-  // CHECK-FIXES: bool boolComingFromFloat = floating != 0.0f;
-
-  signed char character = 'a';
-  bool boolComingFromChar = character;
-  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: implicit cast 'signed char' -> bool
-  // CHECK-FIXES: bool boolComingFromChar = character != 0;
-
-  int* pointer = nullptr;
-  bool boolComingFromPointer = pointer;
-  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: implicit cast 'int *' -> bool
-  // CHECK-FIXES: bool boolComingFromPointer = pointer != nullptr;
-}
-
-void implicitCastToBoolInComplexExpressions() {
-  bool boolean = true;
-
-  int integer = 10;
-  int anotherInteger = 20;
-  bool boolComingFromInteger = integer + anotherInteger;
-  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: implicit cast 'int' -> bool
-  // CHECK-FIXES: bool boolComingFromInteger = (integer + anotherInteger) != 0;
-
-  float floating = 0.2f;
-  bool boolComingFromFloating = floating - 0.3f || boolean;
-  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit cast 'float' -> bool
-  // CHECK-FIXES: bool boolComingFromFloating = ((floating - 0.3f) != 0.0f) || boolean;
-
-  double doubleFloating = 0.3;
-  bool boolComingFromDoubleFloating = (doubleFloating - 0.4) && boolean;
-  // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: implicit cast 'double' -> bool
-  // CHECK-FIXES: bool boolComingFromDoubleFloating = ((doubleFloating - 0.4) != 0.0) && boolean;
-}
-
-void implicitCastInNegationExpressions() {
-  int integer = 10;
-  bool boolComingFromNegatedInt = !integer;
-  // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: implicit cast 'int' -> bool
-  // CHECK-FIXES: bool boolComingFromNegatedInt = integer == 0;
-
-  float floating = 10.0f;
-  bool boolComingFromNegatedFloat = ! floating;
-  // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: implicit cast 'float' -> bool
-  // CHECK-FIXES: bool boolComingFromNegatedFloat = floating == 0.0f;
-
-  signed char character = 'a';
-  bool boolComingFromNegatedChar = (! character);
-  // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: implicit cast 'signed char' -> bool
-  // CHECK-FIXES: bool boolComingFromNegatedChar = (character == 0);
-
-  int* pointer = nullptr;
-  bool boolComingFromNegatedPointer = not pointer;
-  // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: implicit cast 'int *' -> bool
-  // CHECK-FIXES: bool boolComingFromNegatedPointer = pointer == nullptr;
-}
-
-void implicitCastToBoolInControlStatements() {
-  int integer = 10;
-  if (integer) {}
-  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: implicit cast 'int' -> bool
-  // CHECK-FIXES: if (integer != 0) {}
-
-  long int longInteger = 0.2f;
-  for (;longInteger;) {}
-  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: implicit cast 'long' -> bool
-  // CHECK-FIXES: for (;longInteger != 0;) {}
-
-  float floating = 0.3f;
-  while (floating) {}
-  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit cast 'float' -> bool
-  // CHECK-FIXES: while (floating != 0.0f) {}
-
-  double doubleFloating = 0.4;
-  do {} while (doubleFloating);
-  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: implicit cast 'double' -> bool
-  // CHECK-FIXES: do {} while (doubleFloating != 0.0);
-}
-
-bool implicitCastToBoolInReturnValue() {
-  float floating = 1.0f;
-  return floating;
-  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit cast 'float' -> bool
-  // CHECK-FIXES: return floating != 0.0f;
-}
-
-void implicitCastToBoolFromLiterals() {
-  functionTaking<bool>(0);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int' -> bool
-  // CHECK-FIXES: functionTaking<bool>(false);
-
-  functionTaking<bool>(1);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int' -> bool
-  // CHECK-FIXES: functionTaking<bool>(true);
-
-  functionTaking<bool>(2ul);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'unsigned long' -> bool
-  // CHECK-FIXES: functionTaking<bool>(true);
-
-
-  functionTaking<bool>(0.0f);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'float' -> bool
-  // CHECK-FIXES: functionTaking<bool>(false);
-
-  functionTaking<bool>(1.0f);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'float' -> bool
-  // CHECK-FIXES: functionTaking<bool>(true);
-
-  functionTaking<bool>(2.0);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'double' -> bool
-  // CHECK-FIXES: functionTaking<bool>(true);
-
-
-  functionTaking<bool>('\0');
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'char' -> bool
-  // CHECK-FIXES: functionTaking<bool>(false);
-
-  functionTaking<bool>('a');
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'char' -> bool
-  // CHECK-FIXES: functionTaking<bool>(true);
-
-
-  functionTaking<bool>("");
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'const char *' -> bool
-  // CHECK-FIXES: functionTaking<bool>(true);
-
-  functionTaking<bool>("abc");
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'const char *' -> bool
-  // CHECK-FIXES: functionTaking<bool>(true);
-
-  functionTaking<bool>(NULL);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'long' -> bool
-  // CHECK-FIXES: functionTaking<bool>(false);
-}
-
-void implicitCastToBoolFromUnaryMinusAndZeroLiterals() {
-  functionTaking<bool>(-0);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int' -> bool
-  // CHECK-FIXES: functionTaking<bool>((-0) != 0);
-
-  functionTaking<bool>(-0.0f);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'float' -> bool
-  // CHECK-FIXES: functionTaking<bool>((-0.0f) != 0.0f);
-
-  functionTaking<bool>(-0.0);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'double' -> bool
-  // CHECK-FIXES: functionTaking<bool>((-0.0) != 0.0);
-}
-
-void implicitCastToBoolInWithOverloadedOperators() {
-  struct UserStruct {
-    int operator()(int x) { return x; }
-    int operator+(int y) { return y; }
-  };
-
-  UserStruct s;
-
-  functionTaking<bool>(s(0));
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int' -> bool
-  // CHECK-FIXES: functionTaking<bool>(s(0) != 0);
-
-  functionTaking<bool>(s + 2);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int' -> bool
-  // CHECK-FIXES: functionTaking<bool>((s + 2) != 0);
-}
-
-int functionReturningInt();
-int* functionReturningPointer();
-
-void ignoreImplicitCastToBoolWhenDeclaringVariableInControlStatements() {
-  if (int integer = functionReturningInt()) {}
-
-  while (int* pointer = functionReturningPointer()) {}
-}
-
-void ignoreExplicitCastsToBool() {
-  int integer = 10;
-  bool boolComingFromInt = static_cast<bool>(integer);
-
-  float floating = 10.0f;
-  bool boolComingFromFloat = static_cast<bool>(floating);
-
-  char character = 'a';
-  bool boolComingFromChar = static_cast<bool>(character);
-
-  int* pointer = nullptr;
-  bool booleanComingFromPointer = static_cast<bool>(pointer);
-}
-
-void ignoreImplicitCastToBoolInMacroExpansions() {
-  int integer = 3;
-
-  #define CAST_TO_BOOL_IN_MACRO_BODY integer && false
-  bool boolFromMacroBody = CAST_TO_BOOL_IN_MACRO_BODY;
-
-  #define CAST_TO_BOOL_IN_MACRO_ARGUMENT(x) x || true
-  bool boolFromMacroArgument = CAST_TO_BOOL_IN_MACRO_ARGUMENT(integer);
-}
-
-namespace ignoreImplicitCastToBoolInTemplateInstantiations {
-
-template<typename T>
-void templateFunction() {
-  T unknownType = 0;
-  bool boolean = unknownType;
-}
-
-void useOfTemplateFunction() {
-  templateFunction<int>();
-}
-
-} // namespace ignoreImplicitCastToBoolInTemplateInstantiations
-
-namespace ignoreUserDefinedConversionOperator {
-
-struct StructWithUserConversion {
-  operator bool();
-};
-
-void useOfUserConversion() {
-  StructWithUserConversion structure;
-  functionTaking<bool>(structure);
-}
-
-} // namespace ignoreUserDefinedConversionOperator
diff --git a/test/clang-tidy/readability-implicit-bool-cast-allow-conditional-casts.cpp b/test/clang-tidy/readability-implicit-bool-conversion-allow-in-conditions.cpp
similarity index 69%
rename from test/clang-tidy/readability-implicit-bool-cast-allow-conditional-casts.cpp
rename to test/clang-tidy/readability-implicit-bool-conversion-allow-in-conditions.cpp
index 19c08ec..13524de 100644
--- a/test/clang-tidy/readability-implicit-bool-cast-allow-conditional-casts.cpp
+++ b/test/clang-tidy/readability-implicit-bool-conversion-allow-in-conditions.cpp
@@ -1,7 +1,7 @@
-// RUN: %check_clang_tidy %s readability-implicit-bool-cast %t \
+// RUN: %check_clang_tidy %s readability-implicit-bool-conversion %t \
 // RUN: -config='{CheckOptions: \
-// RUN:  [{key: readability-implicit-bool-cast.AllowConditionalIntegerCasts, value: 1}, \
-// RUN:   {key: readability-implicit-bool-cast.AllowConditionalPointerCasts, value: 1}]}' \
+// RUN:  [{key: readability-implicit-bool-conversion.AllowIntegerConditions, value: 1}, \
+// RUN:   {key: readability-implicit-bool-conversion.AllowPointerConditions, value: 1}]}' \
 // RUN: -- -std=c++11
 
 template<typename T>
@@ -15,14 +15,14 @@
 };
 
 
-void regularImplicitCastIntegerToBoolIsNotIgnored() {
+void regularImplicitConversionIntegerToBoolIsNotIgnored() {
   int integer = 0;
   functionTaking<bool>(integer);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int' -> bool [readability-implicit-bool-cast]
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool [readability-implicit-bool-conversion]
   // CHECK-FIXES: functionTaking<bool>(integer != 0);
 }
 
-void implicitCastIntegerToBoolInConditionalsIsAllowed() {
+void implicitConversionIntegerToBoolInConditionalsIsAllowed() {
   if (functionReturningInt()) {}
   if (!functionReturningInt()) {}
   if (functionReturningInt() && functionReturningPointer()) {}
@@ -40,19 +40,19 @@
   int *p1 = functionReturningPointer() ?: &value3;
 }
 
-void regularImplicitCastPointerToBoolIsNotIgnored() {
+void regularImplicitConversionPointerToBoolIsNotIgnored() {
   int* pointer = nullptr;
   functionTaking<bool>(pointer);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int *' -> bool
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int *' -> bool
   // CHECK-FIXES: functionTaking<bool>(pointer != nullptr);
 
   int Struct::* memberPointer = &Struct::member;
   functionTaking<bool>(memberPointer);
-  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int Struct::*' -> bool
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int Struct::*' -> bool
   // CHECK-FIXES: functionTaking<bool>(memberPointer != nullptr);
 }
 
-void implicitCastPointerToBoolInConditionalsIsAllowed() {
+void implicitConversionPointerToBoolInConditionalsIsAllowed() {
   if (functionReturningPointer()) {}
   if (not functionReturningPointer()) {}
   int value1 = functionReturningPointer() ? 1 : 2;
diff --git a/test/clang-tidy/readability-implicit-bool-conversion-cxx98.cpp b/test/clang-tidy/readability-implicit-bool-conversion-cxx98.cpp
new file mode 100644
index 0000000..587f7e2
--- /dev/null
+++ b/test/clang-tidy/readability-implicit-bool-conversion-cxx98.cpp
@@ -0,0 +1,45 @@
+// RUN: %check_clang_tidy %s readability-implicit-bool-conversion %t -- -- -std=c++98
+
+// We need NULL macro, but some buildbots don't like including <cstddef> header
+// This is a portable way of getting it to work
+#undef NULL
+#define NULL 0L
+
+template<typename T>
+void functionTaking(T);
+
+struct Struct {
+  int member;
+};
+
+void useOldNullMacroInReplacements() {
+  int* pointer = NULL;
+  functionTaking<bool>(pointer);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int *' -> bool [readability-implicit-bool-conversion]
+  // CHECK-FIXES: functionTaking<bool>(pointer != 0);
+
+  int Struct::* memberPointer = NULL;
+  functionTaking<bool>(!memberPointer);
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit conversion 'int Struct::*' -> bool
+  // CHECK-FIXES: functionTaking<bool>(memberPointer == 0);
+}
+
+void fixFalseLiteralConvertingToNullPointer() {
+  functionTaking<int*>(false);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion bool -> 'int *'
+  // CHECK-FIXES: functionTaking<int*>(0);
+
+  int* pointer = NULL;
+  if (pointer == false) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: implicit conversion bool -> 'int *'
+  // CHECK-FIXES: if (pointer == 0) {}
+
+  functionTaking<int Struct::*>(false);
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit conversion bool -> 'int Struct::*'
+  // CHECK-FIXES: functionTaking<int Struct::*>(0);
+
+  int Struct::* memberPointer = NULL;
+  if (memberPointer != false) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion bool -> 'int Struct::*'
+  // CHECK-FIXES: if (memberPointer != 0) {}
+}
diff --git a/test/clang-tidy/readability-implicit-bool-conversion.cpp b/test/clang-tidy/readability-implicit-bool-conversion.cpp
new file mode 100644
index 0000000..0bdd670
--- /dev/null
+++ b/test/clang-tidy/readability-implicit-bool-conversion.cpp
@@ -0,0 +1,439 @@
+// RUN: %check_clang_tidy %s readability-implicit-bool-conversion %t
+
+// We need NULL macro, but some buildbots don't like including <cstddef> header
+// This is a portable way of getting it to work
+#undef NULL
+#define NULL 0L
+
+template<typename T>
+void functionTaking(T);
+
+struct Struct {
+  int member;
+};
+
+
+////////// Implicit conversion from bool.
+
+void implicitConversionFromBoolSimpleCases() {
+  bool boolean = true;
+
+  functionTaking<bool>(boolean);
+
+  functionTaking<int>(boolean);
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: implicit conversion bool -> 'int' [readability-implicit-bool-conversion]
+  // CHECK-FIXES: functionTaking<int>(static_cast<int>(boolean));
+
+  functionTaking<unsigned long>(boolean);
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit conversion bool -> 'unsigned long'
+  // CHECK-FIXES: functionTaking<unsigned long>(static_cast<unsigned long>(boolean));
+
+  functionTaking<char>(boolean);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion bool -> 'char'
+  // CHECK-FIXES: functionTaking<char>(static_cast<char>(boolean));
+
+  functionTaking<float>(boolean);
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit conversion bool -> 'float'
+  // CHECK-FIXES: functionTaking<float>(static_cast<float>(boolean));
+
+  functionTaking<double>(boolean);
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: implicit conversion bool -> 'double'
+  // CHECK-FIXES: functionTaking<double>(static_cast<double>(boolean));
+}
+
+float implicitConversionFromBoolInReturnValue() {
+  bool boolean = false;
+  return boolean;
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit conversion bool -> 'float'
+  // CHECK-FIXES: return static_cast<float>(boolean);
+}
+
+void implicitConversionFromBoolInSingleBoolExpressions(bool b1, bool b2) {
+  bool boolean = true;
+  boolean = b1 ^ b2;
+  boolean = b1 && b2;
+  boolean |= !b1 || !b2;
+  boolean &= b1;
+  boolean = b1 == true;
+  boolean = b2 != false;
+
+  int integer = boolean - 3;
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: implicit conversion bool -> 'int'
+  // CHECK-FIXES: int integer = static_cast<int>(boolean) - 3;
+
+  float floating = boolean / 0.3f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: implicit conversion bool -> 'float'
+  // CHECK-FIXES: float floating = static_cast<float>(boolean) / 0.3f;
+
+  char character = boolean;
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: implicit conversion bool -> 'char'
+  // CHECK-FIXES: char character = static_cast<char>(boolean);
+}
+
+void implicitConversionFromBoollInComplexBoolExpressions() {
+  bool boolean = true;
+  bool anotherBoolean = false;
+
+  int integer = boolean && anotherBoolean;
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: implicit conversion bool -> 'int'
+  // CHECK-FIXES: int integer = static_cast<int>(boolean && anotherBoolean);
+
+  unsigned long unsignedLong = (! boolean) + 4ul;
+  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: implicit conversion bool -> 'unsigned long'
+  // CHECK-FIXES: unsigned long unsignedLong = static_cast<unsigned long>(! boolean) + 4ul;
+
+  float floating = (boolean || anotherBoolean) * 0.3f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: implicit conversion bool -> 'float'
+  // CHECK-FIXES: float floating = static_cast<float>(boolean || anotherBoolean) * 0.3f;
+
+  double doubleFloating = (boolean && (anotherBoolean || boolean)) * 0.3;
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: implicit conversion bool -> 'double'
+  // CHECK-FIXES: double doubleFloating = static_cast<double>(boolean && (anotherBoolean || boolean)) * 0.3;
+}
+
+void implicitConversionFromBoolLiterals() {
+  functionTaking<int>(true);
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: implicit conversion bool -> 'int'
+  // CHECK-FIXES: functionTaking<int>(1);
+
+  functionTaking<unsigned long>(false);
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit conversion bool -> 'unsigned long'
+  // CHECK-FIXES: functionTaking<unsigned long>(0u);
+
+  functionTaking<signed char>(true);
+  // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: implicit conversion bool -> 'signed char'
+  // CHECK-FIXES: functionTaking<signed char>(1);
+
+  functionTaking<float>(false);
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit conversion bool -> 'float'
+  // CHECK-FIXES: functionTaking<float>(0.0f);
+
+  functionTaking<double>(true);
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: implicit conversion bool -> 'double'
+  // CHECK-FIXES: functionTaking<double>(1.0);
+}
+
+void implicitConversionFromBoolInComparisons() {
+  bool boolean = true;
+  int integer = 0;
+
+  functionTaking<bool>(boolean == integer);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion bool -> 'int'
+  // CHECK-FIXES: functionTaking<bool>(static_cast<int>(boolean) == integer);
+
+  functionTaking<bool>(integer != boolean);
+  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: implicit conversion bool -> 'int'
+  // CHECK-FIXES: functionTaking<bool>(integer != static_cast<int>(boolean));
+}
+
+void ignoreBoolComparisons() {
+  bool boolean = true;
+  bool anotherBoolean = false;
+
+  functionTaking<bool>(boolean == anotherBoolean);
+  functionTaking<bool>(boolean != anotherBoolean);
+}
+
+void ignoreExplicitCastsFromBool() {
+  bool boolean = true;
+
+  int integer = static_cast<int>(boolean) + 3;
+  float floating = static_cast<float>(boolean) * 0.3f;
+  char character = static_cast<char>(boolean);
+}
+
+void ignoreImplicitConversionFromBoolInMacroExpansions() {
+  bool boolean = true;
+
+  #define CAST_FROM_BOOL_IN_MACRO_BODY boolean + 3
+  int integerFromMacroBody = CAST_FROM_BOOL_IN_MACRO_BODY;
+
+  #define CAST_FROM_BOOL_IN_MACRO_ARGUMENT(x) x + 3
+  int integerFromMacroArgument = CAST_FROM_BOOL_IN_MACRO_ARGUMENT(boolean);
+}
+
+namespace ignoreImplicitConversionFromBoolInTemplateInstantiations {
+
+template<typename T>
+void templateFunction() {
+  bool boolean = true;
+  T uknownType = boolean + 3;
+}
+
+void useOfTemplateFunction() {
+  templateFunction<int>();
+}
+
+} // namespace ignoreImplicitConversionFromBoolInTemplateInstantiations
+
+////////// Implicit conversions to bool.
+
+void implicitConversionToBoolSimpleCases() {
+  int integer = 10;
+  functionTaking<bool>(integer);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool
+  // CHECK-FIXES: functionTaking<bool>(integer != 0);
+
+  unsigned long unsignedLong = 10;
+  functionTaking<bool>(unsignedLong);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'unsigned long' -> bool
+  // CHECK-FIXES: functionTaking<bool>(unsignedLong != 0u);
+
+  float floating = 0.0f;
+  functionTaking<bool>(floating);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'float' -> bool
+  // CHECK-FIXES: functionTaking<bool>(floating != 0.0f);
+
+  double doubleFloating = 1.0f;
+  functionTaking<bool>(doubleFloating);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'double' -> bool
+  // CHECK-FIXES: functionTaking<bool>(doubleFloating != 0.0);
+
+  signed char character = 'a';
+  functionTaking<bool>(character);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'signed char' -> bool
+  // CHECK-FIXES: functionTaking<bool>(character != 0);
+
+  int* pointer = nullptr;
+  functionTaking<bool>(pointer);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int *' -> bool
+  // CHECK-FIXES: functionTaking<bool>(pointer != nullptr);
+
+  auto pointerToMember = &Struct::member;
+  functionTaking<bool>(pointerToMember);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int Struct::*' -> bool
+  // CHECK-FIXES: functionTaking<bool>(pointerToMember != nullptr);
+}
+
+void implicitConversionToBoolInSingleExpressions() {
+  int integer = 10;
+  bool boolComingFromInt = integer;
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: implicit conversion 'int' -> bool
+  // CHECK-FIXES: bool boolComingFromInt = integer != 0;
+
+  float floating = 10.0f;
+  bool boolComingFromFloat = floating;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: implicit conversion 'float' -> bool
+  // CHECK-FIXES: bool boolComingFromFloat = floating != 0.0f;
+
+  signed char character = 'a';
+  bool boolComingFromChar = character;
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: implicit conversion 'signed char' -> bool
+  // CHECK-FIXES: bool boolComingFromChar = character != 0;
+
+  int* pointer = nullptr;
+  bool boolComingFromPointer = pointer;
+  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: implicit conversion 'int *' -> bool
+  // CHECK-FIXES: bool boolComingFromPointer = pointer != nullptr;
+}
+
+void implicitConversionToBoolInComplexExpressions() {
+  bool boolean = true;
+
+  int integer = 10;
+  int anotherInteger = 20;
+  bool boolComingFromInteger = integer + anotherInteger;
+  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: implicit conversion 'int' -> bool
+  // CHECK-FIXES: bool boolComingFromInteger = (integer + anotherInteger) != 0;
+
+  float floating = 0.2f;
+  bool boolComingFromFloating = floating - 0.3f || boolean;
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit conversion 'float' -> bool
+  // CHECK-FIXES: bool boolComingFromFloating = ((floating - 0.3f) != 0.0f) || boolean;
+
+  double doubleFloating = 0.3;
+  bool boolComingFromDoubleFloating = (doubleFloating - 0.4) && boolean;
+  // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: implicit conversion 'double' -> bool
+  // CHECK-FIXES: bool boolComingFromDoubleFloating = ((doubleFloating - 0.4) != 0.0) && boolean;
+}
+
+void implicitConversionInNegationExpressions() {
+  int integer = 10;
+  bool boolComingFromNegatedInt = !integer;
+  // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: implicit conversion 'int' -> bool
+  // CHECK-FIXES: bool boolComingFromNegatedInt = integer == 0;
+
+  float floating = 10.0f;
+  bool boolComingFromNegatedFloat = ! floating;
+  // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: implicit conversion 'float' -> bool
+  // CHECK-FIXES: bool boolComingFromNegatedFloat = floating == 0.0f;
+
+  signed char character = 'a';
+  bool boolComingFromNegatedChar = (! character);
+  // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: implicit conversion 'signed char' -> bool
+  // CHECK-FIXES: bool boolComingFromNegatedChar = (character == 0);
+
+  int* pointer = nullptr;
+  bool boolComingFromNegatedPointer = not pointer;
+  // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: implicit conversion 'int *' -> bool
+  // CHECK-FIXES: bool boolComingFromNegatedPointer = pointer == nullptr;
+}
+
+void implicitConversionToBoolInControlStatements() {
+  int integer = 10;
+  if (integer) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: implicit conversion 'int' -> bool
+  // CHECK-FIXES: if (integer != 0) {}
+
+  long int longInteger = 0.2f;
+  for (;longInteger;) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: implicit conversion 'long' -> bool
+  // CHECK-FIXES: for (;longInteger != 0;) {}
+
+  float floating = 0.3f;
+  while (floating) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit conversion 'float' -> bool
+  // CHECK-FIXES: while (floating != 0.0f) {}
+
+  double doubleFloating = 0.4;
+  do {} while (doubleFloating);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: implicit conversion 'double' -> bool
+  // CHECK-FIXES: do {} while (doubleFloating != 0.0);
+}
+
+bool implicitConversionToBoolInReturnValue() {
+  float floating = 1.0f;
+  return floating;
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit conversion 'float' -> bool
+  // CHECK-FIXES: return floating != 0.0f;
+}
+
+void implicitConversionToBoolFromLiterals() {
+  functionTaking<bool>(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool
+  // CHECK-FIXES: functionTaking<bool>(false);
+
+  functionTaking<bool>(1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool
+  // CHECK-FIXES: functionTaking<bool>(true);
+
+  functionTaking<bool>(2ul);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'unsigned long' -> bool
+  // CHECK-FIXES: functionTaking<bool>(true);
+
+
+  functionTaking<bool>(0.0f);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'float' -> bool
+  // CHECK-FIXES: functionTaking<bool>(false);
+
+  functionTaking<bool>(1.0f);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'float' -> bool
+  // CHECK-FIXES: functionTaking<bool>(true);
+
+  functionTaking<bool>(2.0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'double' -> bool
+  // CHECK-FIXES: functionTaking<bool>(true);
+
+
+  functionTaking<bool>('\0');
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'char' -> bool
+  // CHECK-FIXES: functionTaking<bool>(false);
+
+  functionTaking<bool>('a');
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'char' -> bool
+  // CHECK-FIXES: functionTaking<bool>(true);
+
+
+  functionTaking<bool>("");
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'const char *' -> bool
+  // CHECK-FIXES: functionTaking<bool>(true);
+
+  functionTaking<bool>("abc");
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'const char *' -> bool
+  // CHECK-FIXES: functionTaking<bool>(true);
+
+  functionTaking<bool>(NULL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'long' -> bool
+  // CHECK-FIXES: functionTaking<bool>(false);
+}
+
+void implicitConversionToBoolFromUnaryMinusAndZeroLiterals() {
+  functionTaking<bool>(-0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool
+  // CHECK-FIXES: functionTaking<bool>((-0) != 0);
+
+  functionTaking<bool>(-0.0f);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'float' -> bool
+  // CHECK-FIXES: functionTaking<bool>((-0.0f) != 0.0f);
+
+  functionTaking<bool>(-0.0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'double' -> bool
+  // CHECK-FIXES: functionTaking<bool>((-0.0) != 0.0);
+}
+
+void implicitConversionToBoolInWithOverloadedOperators() {
+  struct UserStruct {
+    int operator()(int x) { return x; }
+    int operator+(int y) { return y; }
+  };
+
+  UserStruct s;
+
+  functionTaking<bool>(s(0));
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool
+  // CHECK-FIXES: functionTaking<bool>(s(0) != 0);
+
+  functionTaking<bool>(s + 2);
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool
+  // CHECK-FIXES: functionTaking<bool>((s + 2) != 0);
+}
+
+int functionReturningInt();
+int* functionReturningPointer();
+
+void ignoreImplicitConversionToBoolWhenDeclaringVariableInControlStatements() {
+  if (int integer = functionReturningInt()) {}
+
+  while (int* pointer = functionReturningPointer()) {}
+}
+
+void ignoreExplicitCastsToBool() {
+  int integer = 10;
+  bool boolComingFromInt = static_cast<bool>(integer);
+
+  float floating = 10.0f;
+  bool boolComingFromFloat = static_cast<bool>(floating);
+
+  char character = 'a';
+  bool boolComingFromChar = static_cast<bool>(character);
+
+  int* pointer = nullptr;
+  bool booleanComingFromPointer = static_cast<bool>(pointer);
+}
+
+void ignoreImplicitConversionToBoolInMacroExpansions() {
+  int integer = 3;
+
+  #define CAST_TO_BOOL_IN_MACRO_BODY integer && false
+  bool boolFromMacroBody = CAST_TO_BOOL_IN_MACRO_BODY;
+
+  #define CAST_TO_BOOL_IN_MACRO_ARGUMENT(x) x || true
+  bool boolFromMacroArgument = CAST_TO_BOOL_IN_MACRO_ARGUMENT(integer);
+}
+
+namespace ignoreImplicitConversionToBoolInTemplateInstantiations {
+
+template<typename T>
+void templateFunction() {
+  T unknownType = 0;
+  bool boolean = unknownType;
+}
+
+void useOfTemplateFunction() {
+  templateFunction<int>();
+}
+
+} // namespace ignoreImplicitConversionToBoolInTemplateInstantiations
+
+namespace ignoreUserDefinedConversionOperator {
+
+struct StructWithUserConversion {
+  operator bool();
+};
+
+void useOfUserConversion() {
+  StructWithUserConversion structure;
+  functionTaking<bool>(structure);
+}
+
+} // namespace ignoreUserDefinedConversionOperator
diff --git a/test/clang-tidy/readability-redundant-declaration-ignore-macros.cpp b/test/clang-tidy/readability-redundant-declaration-ignore-macros.cpp
new file mode 100644
index 0000000..2dc8618
--- /dev/null
+++ b/test/clang-tidy/readability-redundant-declaration-ignore-macros.cpp
@@ -0,0 +1,22 @@
+// RUN: %check_clang_tidy %s readability-redundant-declaration %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN:             [{key: readability-redundant-declaration.IgnoreMacros, \
+// RUN:               value: 1}]}" \
+// RUN:   -- -std=c++11
+
+extern int Xyz;
+extern int Xyz; // Xyz
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant 'Xyz' declaration [readability-redundant-declaration]
+// CHECK-FIXES: {{^}}// Xyz{{$}}
+
+namespace macros {
+#define DECLARE(x) extern int x
+#define DEFINE(x) extern int x; int x = 42
+DECLARE(test);
+DEFINE(test);
+// CHECK-FIXES: {{^}}#define DECLARE(x) extern int x{{$}}
+// CHECK-FIXES: {{^}}#define DEFINE(x) extern int x; int x = 42{{$}}
+// CHECK-FIXES: {{^}}DECLARE(test);{{$}}
+// CHECK-FIXES: {{^}}DEFINE(test);{{$}}
+
+} // namespace macros
diff --git a/test/clang-tidy/readability-redundant-declaration.cpp b/test/clang-tidy/readability-redundant-declaration.cpp
index e1b8023..83d1b5b 100644
--- a/test/clang-tidy/readability-redundant-declaration.cpp
+++ b/test/clang-tidy/readability-redundant-declaration.cpp
@@ -1,4 +1,8 @@
-// RUN: %check_clang_tidy %s readability-redundant-declaration %t
+// RUN: %check_clang_tidy %s readability-redundant-declaration %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN:             [{key: readability-redundant-declaration.IgnoreMacros, \
+// RUN:               value: 0}]}" \
+// RUN:   -- -std=c++11
 
 extern int Xyz;
 extern int Xyz; // Xyz
@@ -42,3 +46,25 @@
 
 template <class T>
 C2<T>::C2() = default;
+
+void best_friend();
+
+struct Friendly {
+  friend void best_friend();
+  friend void enemy();
+};
+
+void enemy();
+
+namespace macros {
+#define DECLARE(x) extern int x
+#define DEFINE(x) extern int x; int x = 42
+DECLARE(test);
+DEFINE(test);
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant 'test' declaration
+// CHECK-FIXES: {{^}}#define DECLARE(x) extern int x{{$}}
+// CHECK-FIXES: {{^}}#define DEFINE(x) extern int x; int x = 42{{$}}
+// CHECK-FIXES: {{^}}DECLARE(test);{{$}}
+// CHECK-FIXES: {{^}}DEFINE(test);{{$}}
+
+} // namespace macros
diff --git a/test/clang-tidy/readability-redundant-function-ptr-dereference.cpp b/test/clang-tidy/readability-redundant-function-ptr-dereference.cpp
index 4e324ab..2b34ce1 100644
--- a/test/clang-tidy/readability-redundant-function-ptr-dereference.cpp
+++ b/test/clang-tidy/readability-redundant-function-ptr-dereference.cpp
@@ -16,6 +16,27 @@
   // CHECK-FIXES: (*p)(2);
 }
 
+template<typename T>
+void invoke(const T& fn) {
+  fn(0); // 1
+  (*fn)(0); // 2
+  // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: redundant repeated
+  // CHECK-FIXES: fn(0); // 1
+  // CHECK-FIXES: (fn)(0); // 2
+  // FIXME: Remove unnecessary parentheses.
+}
+
+void f1(int);
+void f2(double);
+void f3(char);
+
+void instantiate() {
+  invoke(f1);
+  invoke(f2);
+  invoke(f3);
+  invoke([](unsigned) {});
+}
+
 void negative() {
   void (*q)(int) = &f;
 
diff --git a/test/clang-tidy/readability-redundant-member-init.cpp b/test/clang-tidy/readability-redundant-member-init.cpp
index f15cb1b..90b52fd 100644
--- a/test/clang-tidy/readability-redundant-member-init.cpp
+++ b/test/clang-tidy/readability-redundant-member-init.cpp
@@ -105,6 +105,17 @@
   // CHECK-FIXES: F8()  {}
 };
 
+// Anonymous struct
+struct F9 {
+  F9() : s1() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for member 's1' is redundant
+  // CHECK-FIXES: F9()  {}
+  struct {
+    S s1;
+    S s2;
+  };
+};
+
 // Initializer not written
 struct NF1 {
   NF1() {}
@@ -197,3 +208,12 @@
   NF14() : f() {}
   V f;
 };
+
+// Anonymous union member
+struct NF15 {
+  NF15() : s1() {}
+  union {
+    S s1;
+    S s2;
+  };
+};
diff --git a/test/clang-tidy/readability-redundant-smartptr-get.cpp b/test/clang-tidy/readability-redundant-smartptr-get.cpp
index 985efc5..ce4c34b 100644
--- a/test/clang-tidy/readability-redundant-smartptr-get.cpp
+++ b/test/clang-tidy/readability-redundant-smartptr-get.cpp
@@ -97,6 +97,12 @@
   // CHECK-MESSAGES: int i = *ip.get();
   // CHECK-FIXES: int i = *ip;
 
+  auto ip2 = ip;
+  i = *ip2.get();
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call
+  // CHECK-MESSAGES: i = *ip2.get();
+  // CHECK-FIXES: i = *ip2;
+
   std::unique_ptr<int> uu;
   std::shared_ptr<double> *ss;
   bool bb = uu.get() == nullptr;
diff --git a/test/clang-tidy/readability-static-accessed-through-instance-nesting-threshold.cpp b/test/clang-tidy/readability-static-accessed-through-instance-nesting-threshold.cpp
new file mode 100644
index 0000000..0375249
--- /dev/null
+++ b/test/clang-tidy/readability-static-accessed-through-instance-nesting-threshold.cpp
@@ -0,0 +1,33 @@
+// RUN: %check_clang_tidy %s readability-static-accessed-through-instance %t -- -config="{CheckOptions: [{key: readability-static-accessed-through-instance.NameSpecifierNestingThreshold, value: 4}]}" --
+
+// Nested specifiers
+namespace M {
+namespace N {
+struct V {
+  static int v;
+  struct T {
+    static int t;
+    struct U {
+      static int u;
+    };
+  };
+};
+}
+}
+
+void f(M::N::V::T::U u) {
+  M::N::V v;
+  v.v = 12;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  M::N::V::v = 12;{{$}}
+
+  M::N::V::T w;
+  w.t = 12;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  M::N::V::T::t = 12;{{$}}
+
+  // u.u is not changed, because the nesting level is over 4
+  u.u = 12;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  u.u = 12;{{$}}
+}
diff --git a/test/clang-tidy/readability-static-accessed-through-instance.cpp b/test/clang-tidy/readability-static-accessed-through-instance.cpp
new file mode 100644
index 0000000..fc42a1d
--- /dev/null
+++ b/test/clang-tidy/readability-static-accessed-through-instance.cpp
@@ -0,0 +1,222 @@
+// RUN: %check_clang_tidy %s readability-static-accessed-through-instance %t
+
+struct C {
+  static void foo();
+  static int x;
+  int nsx;
+  void mf() {
+    (void)&x;    // OK, x is accessed inside the struct.
+    (void)&C::x; // OK, x is accessed using a qualified-id.
+    foo();       // OK, foo() is accessed inside the struct.
+  }
+  void ns() const;
+};
+
+int C::x = 0;
+
+struct CC {
+  void foo();
+  int x;
+};
+
+template <typename T> struct CT {
+  static T foo();
+  static T x;
+  int nsx;
+  void mf() {
+    (void)&x;    // OK, x is accessed inside the struct.
+    (void)&C::x; // OK, x is accessed using a qualified-id.
+    foo();       // OK, foo() is accessed inside the struct.
+  }
+};
+
+// Expressions with side effects
+C &f(int, int, int, int);
+void g() {
+  f(1, 2, 3, 4).x;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through instance  [readability-static-accessed-through-instance]
+  // CHECK-FIXES: {{^}}  f(1, 2, 3, 4).x;{{$}}
+}
+
+int i(int &);
+void j(int);
+C h();
+bool a();
+int k(bool);
+
+void f(C c) {
+  j(i(h().x));
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: static member
+  // CHECK-FIXES: {{^}}  j(i(h().x));{{$}}
+
+  // The execution of h() depends on the return value of a().
+  j(k(a() && h().x));
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: static member
+  // CHECK-FIXES: {{^}}  j(k(a() && h().x));{{$}}
+
+  if ([c]() {
+        c.ns();
+        return c;
+      }().x == 15)
+    ;
+  // CHECK-MESSAGES: :[[@LINE-5]]:7: warning: static member
+  // CHECK-FIXES: {{^}}  if ([c]() {{{$}}
+}
+
+// Nested specifiers
+namespace N {
+struct V {
+  static int v;
+  struct T {
+    static int t;
+    struct U {
+      static int u;
+    };
+  };
+};
+}
+
+void f(N::V::T::U u) {
+  N::V v;
+  v.v = 12;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  N::V::v = 12;{{$}}
+
+  N::V::T w;
+  w.t = 12;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  N::V::T::t = 12;{{$}}
+
+  // u.u is not changed to N::V::T::U::u; because the nesting level is over 3.
+  u.u = 12;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  u.u = 12;{{$}}
+
+  using B = N::V::T::U;
+  B b;
+  b.u;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  B::u;{{$}}
+}
+
+// Templates
+template <typename T> T CT<T>::x;
+
+template <typename T> struct CCT {
+  T foo();
+  T x;
+};
+
+typedef C D;
+
+using E = D;
+
+#define FOO(c) c.foo()
+#define X(c) c.x
+
+template <typename T> void f(T t, C c) {
+  t.x; // OK, t is a template parameter.
+  c.x;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  C::x;{{$}}
+}
+
+template <int N> struct S { static int x; };
+
+template <> struct S<0> { int x; };
+
+template <int N> void h() {
+  S<N> sN;
+  sN.x; // OK, value of N affects whether x is static or not.
+
+  S<2> s2;
+  s2.x;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  S<2>::x;{{$}}
+}
+
+void static_through_instance() {
+  C *c1 = new C();
+  c1->foo(); // 1
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  C::foo(); // 1{{$}}
+  c1->x; // 2
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  C::x; // 2{{$}}
+  c1->nsx; // OK, nsx is a non-static member.
+
+  const C *c2 = new C();
+  c2->foo(); // 2
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  C::foo(); // 2{{$}}
+
+  C::foo(); // OK, foo() is accessed using a qualified-id.
+  C::x;     // OK, x is accessed using a qualified-id.
+
+  D d;
+  d.foo();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  D::foo();{{$}}
+  d.x;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  D::x;{{$}}
+
+  E e;
+  e.foo();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  E::foo();{{$}}
+  e.x;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  E::x;{{$}}
+
+  CC *cc = new CC;
+
+  f(*c1, *c1);
+  f(*cc, *c1);
+
+  // Macros: OK, macros are not checked.
+  FOO((*c1));
+  X((*c1));
+  FOO((*cc));
+  X((*cc));
+
+  // Templates
+  CT<int> ct;
+  ct.foo();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  CT<int>::foo();{{$}}
+  ct.x;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
+  // CHECK-FIXES: {{^}}  CT<int>::x;{{$}}
+  ct.nsx; // OK, nsx is a non-static member
+
+  CCT<int> cct;
+  cct.foo(); // OK, CCT has no static members.
+  cct.x;     // OK, CCT has no static members.
+
+  h<4>();
+}
+
+// Overloaded member access operator
+struct Q {
+  static int K;
+  int y = 0;
+};
+
+int Q::K = 0;
+
+struct Qptr {
+  Q *q;
+
+  explicit Qptr(Q *qq) : q(qq) {}
+
+  Q *operator->() {
+    ++q->y;
+    return q;
+  }
+};
+
+int func(Qptr qp) {
+  qp->y = 10; // OK, the overloaded operator might have side-effects.
+  qp->K = 10; //
+}
diff --git a/test/clang-tidy/readability-uniqueptr-delete-release.cpp b/test/clang-tidy/readability-uniqueptr-delete-release.cpp
index aa8ae25..bd51bc6 100644
--- a/test/clang-tidy/readability-uniqueptr-delete-release.cpp
+++ b/test/clang-tidy/readability-uniqueptr-delete-release.cpp
@@ -24,6 +24,11 @@
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer '= nullptr' to 'delete x.release()' to reset unique_ptr<> objects [readability-uniqueptr-delete-release]
   // CHECK-FIXES: {{^}}  P = nullptr;
 
+  auto P2 = P;
+  delete P2.release();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer '= nullptr' to 'delete x.release()' to reset unique_ptr<> objects [readability-uniqueptr-delete-release]
+  // CHECK-FIXES: {{^}}  P2 = nullptr;
+
   std::unique_ptr<int> Array[20];
   delete Array[4].release();
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer '= nullptr' to 'delete
diff --git a/test/clangd/authority-less-uri.test b/test/clangd/authority-less-uri.test
index f52f0ea..1a21c10 100644
--- a/test/clangd/authority-less-uri.test
+++ b/test/clangd/authority-less-uri.test
@@ -16,7 +16,7 @@
 # Test authority-less URI

 #

 # CHECK: {"jsonrpc":"2.0","id":1,"result":[

-# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"99964a","filterText":"a","insertText":"a"}

+# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"000035a","filterText":"a","insertText":"a","insertTextFormat":1}

 # CHECK: ]}

 

 Content-Length: 172

@@ -25,7 +25,7 @@
 # Test params parsing in the presence of a 1.x-compatible client (inlined "uri")

 #

 # CHECK: {"jsonrpc":"2.0","id":2,"result":[

-# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"99964a","filterText":"a","insertText":"a"}

+# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"000035a","filterText":"a","insertText":"a","insertTextFormat":1}

 # CHECK: ]}

 Content-Length: 44

 

diff --git a/test/clangd/completion-priorities.test b/test/clangd/completion-priorities.test
new file mode 100644
index 0000000..ed90225
--- /dev/null
+++ b/test/clangd/completion-priorities.test
@@ -0,0 +1,36 @@
+# RUN: clangd -run-synchronously < %s | FileCheck %s

+# It is absolutely vital that this file has CRLF line endings.

+#

+

+Content-Length: 127

+

+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}

+

+Content-Length: 312

+

+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"class Foo {\npublic:\n  void pub();\n\nprotected:\n  void prot();\n\nprivate:\n  void priv();\n};\n\nvoid Foo::pub() {\n  this->\n}\n\nvoid test() {\n  Foo f;\n  f.\n}"}}}

+

+Content-Length: 151

+

+{"jsonrpc":"2.0","id":2,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":12,"character":8}}}

+# The order of results returned by codeComplete seems to be

+# nondeterministic, so we check regardless of order.

+#

+# CHECK: {"jsonrpc":"2.0","id":2,"result":[

+# CHECK-DAG: {"label":"pub()","kind":2,"detail":"void","sortText":"000034pub","filterText":"pub","insertText":"pub","insertTextFormat":1}

+# CHECK-DAG: {"label":"prot()","kind":2,"detail":"void","sortText":"000034prot","filterText":"prot","insertText":"prot","insertTextFormat":1}

+# CHECK-DAG: {"label":"priv()","kind":2,"detail":"void","sortText":"000034priv","filterText":"priv","insertText":"priv","insertTextFormat":1}

+# CHECK: ]}

+

+Content-Length: 151

+

+{"jsonrpc":"2.0","id":3,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":4}}}

+# CHECK: {"jsonrpc":"2.0","id":3,"result":[

+# CHECK-DAG: {"label":"pub()","kind":2,"detail":"void","sortText":"000034pub","filterText":"pub","insertText":"pub","insertTextFormat":1}

+# CHECK-DAG: {"label":"prot()","kind":2,"detail":"void","sortText":"200034prot","filterText":"prot","insertText":"prot","insertTextFormat":1}

+# CHECK-DAG: {"label":"priv()","kind":2,"detail":"void","sortText":"200034priv","filterText":"priv","insertText":"priv","insertTextFormat":1}

+# CHECK: ]}

+

+Content-Length: 58

+

+{"jsonrpc":"2.0","id":4,"method":"shutdown","params":null}

diff --git a/test/clangd/completion-qualifiers.test b/test/clangd/completion-qualifiers.test
new file mode 100644
index 0000000..52b7639
--- /dev/null
+++ b/test/clangd/completion-qualifiers.test
@@ -0,0 +1,18 @@
+# RUN: clangd -run-synchronously < %s | FileCheck %s

+Content-Length: 125

+

+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}

+Content-Length: 297

+

+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"class Foo {\n  public:\n    int foo() const;\n    int bar() const;\n};\n\nclass Bar : public Foo {\n  int foo() const;\n};\n\nvoid test() {\n  Bar().\n}"}}}

+Content-Length: 151

+

+{"jsonrpc":"2.0","id":2,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":11,"character":8}}}

+# CHECK: {"jsonrpc":"2.0","id":2,"result":[

+# CHECK-DAG: {"label":"foo() const","kind":2,"detail":"int","sortText":"200035foo","filterText":"foo","insertText":"foo","insertTextFormat":1}

+# CHECK-DAG: {"label":"bar() const","kind":2,"detail":"int","sortText":"000037bar","filterText":"bar","insertText":"bar","insertTextFormat":1}

+# CHECK-DAG: {"label":"Foo::foo() const","kind":2,"detail":"int","sortText":"000037foo","filterText":"foo","insertText":"foo","insertTextFormat":1}

+# CHECK: ]}

+Content-Length: 44

+

+{"jsonrpc":"2.0","id":4,"method":"shutdown"}

diff --git a/test/clangd/completion-snippet.test b/test/clangd/completion-snippet.test
new file mode 100644
index 0000000..4a468a1
--- /dev/null
+++ b/test/clangd/completion-snippet.test
@@ -0,0 +1,54 @@
+# RUN: clangd -run-synchronously -enable-snippets < %s | FileCheck %s

+# It is absolutely vital that this file has CRLF line endings.

+#

+Content-Length: 125

+

+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}

+

+Content-Length: 246

+

+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"struct fake { int a, bb, ccc; int f(int i, const float f) const; };\nint main() {\n  fake f;\n  f.\n}\n"}}}

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":3,"character":5}}}

+# The order of results returned by codeComplete seems to be

+# nondeterministic, so we check regardless of order.

+#

+# CHECK: {"jsonrpc":"2.0","id":1,"result":[

+# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"000035a","filterText":"a","insertText":"a","insertTextFormat":1}

+# CHECK-DAG: {"label":"bb","kind":5,"detail":"int","sortText":"000035bb","filterText":"bb","insertText":"bb","insertTextFormat":1}

+# CHECK-DAG: {"label":"ccc","kind":5,"detail":"int","sortText":"000035ccc","filterText":"ccc","insertText":"ccc","insertTextFormat":1}

+# CHECK-DAG: {"label":"operator=(const fake &)","kind":2,"detail":"fake &","sortText":"000079operator=","filterText":"operator=","insertText":"operator=(${1:const fake &})","insertTextFormat":2}

+# CHECK-DAG: {"label":"~fake()","kind":4,"detail":"void","sortText":"000079~fake","filterText":"~fake","insertText":"~fake()","insertTextFormat":1}

+# CHECK-DAG: {"label":"f(int i, const float f) const","kind":2,"detail":"int","sortText":"000035f","filterText":"f","insertText":"f(${1:int i}, ${2:const float f})","insertTextFormat":2}

+# CHECK: ]}

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":2,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":3,"character":5}}}

+# Repeat the completion request, expect the same results.

+#

+# CHECK: {"jsonrpc":"2.0","id":2,"result":[

+# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"000035a","filterText":"a","insertText":"a","insertTextFormat":1}

+# CHECK-DAG: {"label":"bb","kind":5,"detail":"int","sortText":"000035bb","filterText":"bb","insertText":"bb","insertTextFormat":1}

+# CHECK-DAG: {"label":"ccc","kind":5,"detail":"int","sortText":"000035ccc","filterText":"ccc","insertText":"ccc","insertTextFormat":1}

+# CHECK-DAG: {"label":"operator=(const fake &)","kind":2,"detail":"fake &","sortText":"000079operator=","filterText":"operator=","insertText":"operator=(${1:const fake &})","insertTextFormat":2}

+# CHECK-DAG: {"label":"~fake()","kind":4,"detail":"void","sortText":"000079~fake","filterText":"~fake","insertText":"~fake()","insertTextFormat":1}

+# CHECK-DAG: {"label":"f(int i, const float f) const","kind":2,"detail":"int","sortText":"000035f","filterText":"f","insertText":"f(${1:int i}, ${2:const float f})","insertTextFormat":2}

+# CHECK: ]}

+# Update the source file and check for completions again.

+Content-Length: 226

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":2},"contentChanges":[{"text":"struct fancy { int (*func())(int, int); };\nint main() {\n  fancy f;\n  f.\n}\n"}]}}

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":3,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":3,"character":5}}}

+# Repeat the completion request, expect the same results.

+#

+# CHECK: {"jsonrpc":"2.0","id":3,"result":[

+# CHECK-DAG: {"label":"func()","kind":2,"detail":"int (*)(int, int)","sortText":"000034func","filterText":"func","insertText":"func()","insertTextFormat":1}

+# CHECK: ]}

+Content-Length: 44

+

+{"jsonrpc":"2.0","id":4,"method":"shutdown"}

diff --git a/test/clangd/completion.test b/test/clangd/completion.test
index f99c33b..f15664d 100644
--- a/test/clangd/completion.test
+++ b/test/clangd/completion.test
@@ -12,16 +12,16 @@
 Content-Length: 148

 

 {"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":3,"character":5}}}

-# The order of results returned by ASTUnit CodeComplete seems to be

+# The order of results returned by codeComplete seems to be

 # nondeterministic, so we check regardless of order.

 #

 # CHECK: {"jsonrpc":"2.0","id":1,"result":[

-# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"99964a","filterText":"a","insertText":"a"}

-# CHECK-DAG: {"label":"bb","kind":5,"detail":"int","sortText":"99964bb","filterText":"bb","insertText":"bb"}

-# CHECK-DAG: {"label":"ccc","kind":5,"detail":"int","sortText":"99964ccc","filterText":"ccc","insertText":"ccc"}

-# CHECK-DAG: {"label":"operator=(const fake &)","kind":2,"detail":"fake &","sortText":"99965operator=","filterText":"operator=","insertText":"operator="}

-# CHECK-DAG: {"label":"~fake()","kind":4,"detail":"void","sortText":"99965~fake","filterText":"~fake","insertText":"~fake"}

-# CHECK-DAG: {"label":"f(int i, const float f) const","kind":2,"detail":"int","sortText":"99964f","filterText":"f","insertText":"f"}

+# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"000035a","filterText":"a","insertText":"a","insertTextFormat":1}

+# CHECK-DAG: {"label":"bb","kind":5,"detail":"int","sortText":"000035bb","filterText":"bb","insertText":"bb","insertTextFormat":1}

+# CHECK-DAG: {"label":"ccc","kind":5,"detail":"int","sortText":"000035ccc","filterText":"ccc","insertText":"ccc","insertTextFormat":1}

+# CHECK-DAG: {"label":"operator=(const fake &)","kind":2,"detail":"fake &","sortText":"000079operator=","filterText":"operator=","insertText":"operator=","insertTextFormat":1}

+# CHECK-DAG: {"label":"~fake()","kind":4,"detail":"void","sortText":"000079~fake","filterText":"~fake","insertText":"~fake","insertTextFormat":1}

+# CHECK-DAG: {"label":"f(int i, const float f) const","kind":2,"detail":"int","sortText":"000035f","filterText":"f","insertText":"f","insertTextFormat":1}

 # CHECK: ]}

 Content-Length: 148

 

@@ -29,12 +29,12 @@
 # Repeat the completion request, expect the same results.

 #

 # CHECK: {"jsonrpc":"2.0","id":2,"result":[

-# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"99964a","filterText":"a","insertText":"a"}

-# CHECK-DAG: {"label":"bb","kind":5,"detail":"int","sortText":"99964bb","filterText":"bb","insertText":"bb"}

-# CHECK-DAG: {"label":"ccc","kind":5,"detail":"int","sortText":"99964ccc","filterText":"ccc","insertText":"ccc"}

-# CHECK-DAG: {"label":"operator=(const fake &)","kind":2,"detail":"fake &","sortText":"99965operator=","filterText":"operator=","insertText":"operator="}

-# CHECK-DAG: {"label":"~fake()","kind":4,"detail":"void","sortText":"99965~fake","filterText":"~fake","insertText":"~fake"}

-# CHECK-DAG: {"label":"f(int i, const float f) const","kind":2,"detail":"int","sortText":"99964f","filterText":"f","insertText":"f"}

+# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"000035a","filterText":"a","insertText":"a","insertTextFormat":1}

+# CHECK-DAG: {"label":"bb","kind":5,"detail":"int","sortText":"000035bb","filterText":"bb","insertText":"bb","insertTextFormat":1}

+# CHECK-DAG: {"label":"ccc","kind":5,"detail":"int","sortText":"000035ccc","filterText":"ccc","insertText":"ccc","insertTextFormat":1}

+# CHECK-DAG: {"label":"operator=(const fake &)","kind":2,"detail":"fake &","sortText":"000079operator=","filterText":"operator=","insertText":"operator=","insertTextFormat":1}

+# CHECK-DAG: {"label":"~fake()","kind":4,"detail":"void","sortText":"000079~fake","filterText":"~fake","insertText":"~fake","insertTextFormat":1}

+# CHECK-DAG: {"label":"f(int i, const float f) const","kind":2,"detail":"int","sortText":"000035f","filterText":"f","insertText":"f","insertTextFormat":1}

 # CHECK: ]}

 # Update the source file and check for completions again.

 Content-Length: 226

@@ -47,7 +47,7 @@
 # Repeat the completion request, expect the same results.

 #

 # CHECK: {"jsonrpc":"2.0","id":3,"result":[

-# CHECK-DAG: {"label":"func()","kind":2,"detail":"int (*)(int, int)","sortText":"99965func","filterText":"func","insertText":"func"}

+# CHECK-DAG: {"label":"func()","kind":2,"detail":"int (*)(int, int)","sortText":"000034func","filterText":"func","insertText":"func","insertTextFormat":1}

 # CHECK: ]}

 Content-Length: 44

 

diff --git a/test/clangd/definitions.test b/test/clangd/definitions.test
new file mode 100644
index 0000000..8e305bf
--- /dev/null
+++ b/test/clangd/definitions.test
@@ -0,0 +1,168 @@
+# RUN: clangd -run-synchronously < %s | FileCheck %s

+# It is absolutely vital that this file has CRLF line endings.

+#

+Content-Length: 125

+

+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}

+

+Content-Length: 172

+

+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"int main() {\nint a;\na;\n}\n"}}}

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":2,"character":0}}}

+# Go to local variable

+# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 1, "character": 0}, "end": {"line": 1, "character": 5}}}]}

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":2,"character":1}}}

+# Go to local variable, end of token

+# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 1, "character": 0}, "end": {"line": 1, "character": 5}}}]}

+

+Content-Length: 214

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":2},"contentChanges":[{"text":"struct Foo {\nint x;\n};\nint main() {\n  Foo bar = { x : 1 };\n}\n"}]}}

+

+Content-Length: 149

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":4,"character":14}}}

+# Go to field, GNU old-style field designator 

+# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 1, "character": 0}, "end": {"line": 1, "character": 5}}}]}

+

+Content-Length: 215

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":3},"contentChanges":[{"text":"struct Foo {\nint x;\n};\nint main() {\n  Foo baz = { .x = 2 };\n}\n"}]}}

+

+Content-Length: 149

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":4,"character":15}}}

+# Go to field, field designator 

+# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 1, "character": 0}, "end": {"line": 1, "character": 5}}}]}

+

+Content-Length: 187

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":4},"contentChanges":[{"text":"int main() {\n   main();\n   return 0;\n}"}]}}

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":1,"character":3}}}

+# Go to function declaration, function call 

+# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 0, "character": 0}, "end": {"line": 3, "character": 1}}}]}

+

+Content-Length: 208

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":5},"contentChanges":[{"text":"struct Foo {\n};\nint main() {\n   Foo bar;\n   return 0;\n}\n"}]}}

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":3,"character":3}}}

+# Go to struct declaration, new struct instance 

+# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 0, "character": 0}, "end": {"line": 1, "character": 1}}}]}

+

+Content-Length: 231

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":5},"contentChanges":[{"text":"namespace n1 {\nstruct Foo {\n};\n}\nint main() {\n   n1::Foo bar;\n   return 0;\n}\n"}]}}

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":5,"character":4}}}

+# Go to struct declaration, new struct instance, qualified name 

+# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 0, "character": 0}, "end": {"line": 3, "character": 1}}}]}

+

+Content-Length: 215

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":6},"contentChanges":[{"text":"struct Foo {\n  int x;\n};\nint main() {\n   Foo bar;\n   bar.x;\n}\n"}]}}

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":5,"character":7}}}

+# Go to field declaration, field reference 

+# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 1, "character": 2}, "end": {"line": 1, "character": 7}}}]}

+

+Content-Length: 220

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":7},"contentChanges":[{"text":"struct Foo {\n  void x();\n};\nint main() {\n   Foo bar;\n   bar.x();\n}\n"}]}}

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":5,"character":7}}}

+# Go to method declaration, method call 

+# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 1, "character": 2}, "end": {"line": 1, "character": 10}}}]}

+

+Content-Length: 240

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":7},"contentChanges":[{"text":"struct Foo {\n};\ntypedef Foo TypedefFoo;\nint main() {\n   TypedefFoo bar;\n   return 0;\n}\n"}]}}

+

+Content-Length: 149

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":4,"character":10}}}

+# Go to typedef 

+# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 2, "character": 0}, "end": {"line": 2, "character": 22}}}]}

+

+Content-Length: 254

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":7},"contentChanges":[{"text":"template <typename MyTemplateParam>\nvoid foo() {\n MyTemplateParam a;\n}\nint main() {\n   return 0;\n}\n"}]}}

+

+Content-Length: 149

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":2,"character":13}}}

+# Go to template type parameter. Fails until clangIndex is modified to handle those.

+# no-CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 0, "character": 10}, "end": {"line": 0, "character": 34}}}]}

+

+Content-Length: 256

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":7},"contentChanges":[{"text":"namespace ns {\nstruct Foo {\nstatic void bar() {}\n};\n}\nint main() {\n   ns::Foo::bar();\n   return 0;\n}\n"}]}}

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":6,"character":4}}}

+# Go to namespace, static method call 

+# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 0, "character": 0}, "end": {"line": 4, "character": 1}}}]}

+

+Content-Length: 265

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":7},"contentChanges":[{"text":"namespace ns {\nstruct Foo {\n  int field;\n  Foo(int param) : field(param) {}\n};\n}\nint main() {\n   return 0;\n}\n"}]}}

+

+Content-Length: 149

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":3,"character":21}}}

+# Go to field, member initializer 

+# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 2, "character": 2}, "end": {"line": 2, "character": 11}}}]}

+

+Content-Length: 204

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":7},"contentChanges":[{"text":"#define MY_MACRO 0\nint main() {\n  return MY_MACRO;\n}\n"}]}}

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":2,"character":9}}}

+# Go to macro.

+# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///{{([A-Za-z]:/)?}}main.cpp", "range": {"start": {"line": 0, "character": 8}, "end": {"line": 0, "character": 18}}}]}

+

+Content-Length: 217

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":7},"contentChanges":[{"text":"#define FOO 1\nint a = FOO;\n#define FOO 2\nint b = FOO;\n#undef FOO\n"}]}}

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":1,"character":8}}}

+# Go to macro, re-defined later

+# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///{{([A-Za-z]:/)?}}main.cpp", "range": {"start": {"line": 0, "character": 8}, "end": {"line": 0, "character": 13}}}]}

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":3,"character":8}}}

+# Go to macro, undefined later

+# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 2, "character": 8}, "end": {"line": 2, "character": 13}}}]}

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":4,"character":7}}}

+# Go to macro, being undefined

+# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 2, "character": 8}, "end": {"line": 2, "character": 13}}}]}

+

+Content-Length: 44

+

+{"jsonrpc":"2.0","id":3,"method":"shutdown"}

diff --git a/test/clangd/diagnostics-preamble.test b/test/clangd/diagnostics-preamble.test
new file mode 100644
index 0000000..ac68f05
--- /dev/null
+++ b/test/clangd/diagnostics-preamble.test
@@ -0,0 +1,15 @@
+# RUN: clangd -run-synchronously < %s | FileCheck %s

+# It is absolutely vital that this file has CRLF line endings.

+#

+Content-Length: 125

+

+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}

+

+Content-Length: 206

+

+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#ifndef FOO\n#define FOO\nint a;\n#else\nint a = b;#endif\n\n\n"}}}

+# CHECK: {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///main.cpp","diagnostics":[]}}

+

+Content-Length: 58

+

+{"jsonrpc":"2.0","id":2,"method":"shutdown","params":null}

diff --git a/test/clangd/did-change-watch-files.test b/test/clangd/did-change-watch-files.test
new file mode 100644
index 0000000..aabe1eb
--- /dev/null
+++ b/test/clangd/did-change-watch-files.test
@@ -0,0 +1,61 @@
+# RUN: clangd -run-synchronously < %s 2>&1 | FileCheck -check-prefix=STDERR %s

+# It is absolutely vital that this file has CRLF line endings.

+#

+# Test initialize request parameters with rootUri

+Content-Length: 143

+

+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootUri":"file:///path/to/workspace","capabilities":{},"trace":"off"}}

+# CHECK: Content-Length: 466

+# CHECK: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{

+# CHECK:   "textDocumentSync": 1,

+# CHECK:   "documentFormattingProvider": true,

+# CHECK:   "documentRangeFormattingProvider": true,

+# CHECK:   "documentOnTypeFormattingProvider": {"firstTriggerCharacter":"}","moreTriggerCharacter":[]},

+# CHECK:   "codeActionProvider": true,

+# CHECK:   "completionProvider": {"resolveProvider": false, "triggerCharacters": [".",">",":"]},

+# CHECK:   "definitionProvider": true

+# CHECK: }}}

+#

+#Normal case

+Content-Length: 217

+

+{"jsonrpc":"2.0","method":"workspace/didChangeWatchedFiles","params":{"changes":[{"uri":"file:///path/to/file.cpp","type":1},{"uri":"file:///path/to/file2.cpp","type":2},{"uri":"file:///path/to/file3.cpp","type":3}]}}

+

+# Wrong event type, integer

+Content-Length: 173

+

+{"jsonrpc":"2.0","method":"workspace/didChangeWatchedFiles","params":{"changes":[{"uri":"file:///path/to/file2.cpp","type":0},{"uri":"file:///path/to/file3.cpp","type":4}]}}

+# STDERR: Failed to decode a FileEvent.

+# Wrong event type, string

+Content-Length: 132

+

+{"jsonrpc":"2.0","method":"workspace/didChangeWatchedFiles","params":{"changes":[{"uri":"file:///path/to/file2.cpp","type":"foo"}]}}

+# STDERR: Failed to decode a FileEvent.

+#Custom event field

+Content-Length: 143

+

+{"jsonrpc":"2.0","method":"workspace/didChangeWatchedFiles","params":{"changes":[{"uri":"file:///path/to/file2.cpp","type":1,"custom":"foo"}]}}

+# STDERR: Failed to decode a FileEvent.

+#Event field with object

+Content-Length: 140

+

+{"jsonrpc":"2.0","method":"workspace/didChangeWatchedFiles","params":{"changes":[{"uri":"file:///path/to/file2.cpp","type":{"foo":"bar"}}]}}

+# STDERR: Failed to decode a FileEvent.

+# Changes field with sequence but no object

+Content-Length: 86

+

+{"jsonrpc":"2.0","method":"workspace/didChangeWatchedFiles","params":{"changes":[""]}}

+# STDERR: Failed to decode workspace/didChangeWatchedFiles request.

+# Changes field with no sequence

+Content-Length: 84

+

+{"jsonrpc":"2.0","method":"workspace/didChangeWatchedFiles","params":{"changes":""}}

+# STDERR: Failed to decode workspace/didChangeWatchedFiles request.

+# Custom field

+Content-Length: 86

+

+{"jsonrpc":"2.0","method":"workspace/didChangeWatchedFiles","params":{"custom":"foo"}}

+# STDERR: Ignored unknown field "custom"

+Content-Length: 44

+

+{"jsonrpc":"2.0","id":3,"method":"shutdown"}

diff --git a/test/clangd/extra-flags.test b/test/clangd/extra-flags.test
new file mode 100644
index 0000000..4e5fcc9
--- /dev/null
+++ b/test/clangd/extra-flags.test
@@ -0,0 +1,22 @@
+# RUN: clangd -run-synchronously < %s | FileCheck %s

+# It is absolutely vital that this file has CRLF line endings.

+#

+Content-Length: 125

+

+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}

+#

+Content-Length: 205

+

+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///foo.c","languageId":"c","version":1,"text":"int main() { int i; return i; }"},"metadata":{"extraFlags":["-Wall"]}}}

+# CHECK: {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///foo.c","diagnostics":[{"range":{"start": {"line": 0, "character": 28}, "end": {"line": 0, "character": 28}},"severity":2,"message":"variable 'i' is uninitialized when used here"},{"range":{"start": {"line": 0, "character": 19}, "end": {"line": 0, "character": 19}},"severity":3,"message":"initialize the variable 'i' to silence this warning"}]}}

+#

+Content-Length: 175

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///foo.c","version":2},"contentChanges":[{"text":"int main() { int i; return i; }"}]}}

+# CHECK: {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///foo.c","diagnostics":[{"range":{"start": {"line": 0, "character": 28}, "end": {"line": 0, "character": 28}},"severity":2,"message":"variable 'i' is uninitialized when used here"},{"range":{"start": {"line": 0, "character": 19}, "end": {"line": 0, "character": 19}},"severity":3,"message":"initialize the variable 'i' to silence this warning"}]}}

+#

+Content-Length: 44

+

+{"jsonrpc":"2.0","id":5,"method":"shutdown"}

+

+

diff --git a/test/clangd/fixits.test b/test/clangd/fixits.test
index 7272c3b..a12892d 100644
--- a/test/clangd/fixits.test
+++ b/test/clangd/fixits.test
@@ -15,7 +15,13 @@
 

  {"jsonrpc":"2.0","id":2,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"file:///foo.c"},"range":{"start":{"line":104,"character":13},"end":{"line":0,"character":35}},"context":{"diagnostics":[{"range":{"start": {"line": 0, "character": 35}, "end": {"line": 0, "character": 35}},"severity":2,"message":"using the result of an assignment as a condition without parentheses"},{"range":{"start": {"line": 0, "character": 35}, "end": {"line": 0, "character": 35}},"severity":3,"message":"place parentheses around the assignment to silence this warning"},{"range":{"start": {"line": 0, "character": 35}, "end": {"line": 0, "character": 35}},"severity":3,"message":"use '==' to turn this assignment into an equality comparison"}]}}}

 #

-# CHECK: {"jsonrpc":"2.0","id":2, "result": [{"title":"Apply FixIt 'place parentheses around the assignment to silence this warning'", "command": "clangd.applyFix", "arguments": ["file:///foo.c", [{"range": {"start": {"line": 0, "character": 32}, "end": {"line": 0, "character": 32}}, "newText": "("},{"range": {"start": {"line": 0, "character": 37}, "end": {"line": 0, "character": 37}}, "newText": ")"}]]},{"title":"Apply FixIt 'use '==' to turn this assignment into an equality comparison'", "command": "clangd.applyFix", "arguments": ["file:///foo.c", [{"range": {"start": {"line": 0, "character": 34}, "end": {"line": 0, "character": 35}}, "newText": "=="}]]}]

+# CHECK: {"jsonrpc":"2.0","id":2,"result":[{"title":"Apply FixIt 'place parentheses around the assignment to silence this warning'", "command": "clangd.applyFix", "arguments": ["file:///foo.c", [{"range": {"start": {"line": 0, "character": 32}, "end": {"line": 0, "character": 32}}, "newText": "("},{"range": {"start": {"line": 0, "character": 37}, "end": {"line": 0, "character": 37}}, "newText": ")"}]]},{"title":"Apply FixIt 'use '==' to turn this assignment into an equality comparison'", "command": "clangd.applyFix", "arguments": ["file:///foo.c", [{"range": {"start": {"line": 0, "character": 34}, "end": {"line": 0, "character": 35}}, "newText": "=="}]]}]

+#

+Content-Length: 771

+

+{"jsonrpc":"2.0","id":2,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"file:///foo.c"},"range":{"start":{"line":104,"character":13},"end":{"line":0,"character":35}},"context":{"diagnostics":[{"range":{"start": {"line": 0, "character": 35}, "end": {"line": 0, "character": 35}},"severity":2,"code":"1","source":"foo","message":"using the result of an assignment as a condition without parentheses"},{"range":{"start": {"line": 0, "character": 35}, "end": {"line": 0, "character": 35}},"severity":3,"message":"place parentheses around the assignment to silence this warning"},{"range":{"start": {"line": 0, "character": 35}, "end": {"line": 0, "character": 35}},"severity":3,"message":"use '==' to turn this assignment into an equality comparison"}]}}}

+# Make sure unused "code" and "source" fields ignored gracefully

+# CHECK: {"jsonrpc":"2.0","id":2,"result":[{"title":"Apply FixIt 'place parentheses around the assignment to silence this warning'", "command": "clangd.applyFix", "arguments": ["file:///foo.c", [{"range": {"start": {"line": 0, "character": 32}, "end": {"line": 0, "character": 32}}, "newText": "("},{"range": {"start": {"line": 0, "character": 37}, "end": {"line": 0, "character": 37}}, "newText": ")"}]]},{"title":"Apply FixIt 'use '==' to turn this assignment into an equality comparison'", "command": "clangd.applyFix", "arguments": ["file:///foo.c", [{"range": {"start": {"line": 0, "character": 34}, "end": {"line": 0, "character": 35}}, "newText": "=="}]]}]

 #

 Content-Length: 44

 

diff --git a/test/clangd/formatting.test b/test/clangd/formatting.test
index d0a0cd5..a2a490a 100644
--- a/test/clangd/formatting.test
+++ b/test/clangd/formatting.test
@@ -4,14 +4,14 @@
 Content-Length: 125

 

 {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}

-# CHECK: Content-Length: 424

 # CHECK: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{

 # CHECK:   "textDocumentSync": 1,

 # CHECK:   "documentFormattingProvider": true,

 # CHECK:   "documentRangeFormattingProvider": true,

 # CHECK:   "documentOnTypeFormattingProvider": {"firstTriggerCharacter":"}","moreTriggerCharacter":[]},

 # CHECK:   "codeActionProvider": true,

-# CHECK:   "completionProvider": {"resolveProvider": false, "triggerCharacters": [".",">"]}

+# CHECK:   "completionProvider": {"resolveProvider": false, "triggerCharacters": [".",">",":"]},

+# CHECK:   "definitionProvider": true

 # CHECK: }}}

 #

 Content-Length: 193

diff --git a/test/clangd/initialize-params-invalid.test b/test/clangd/initialize-params-invalid.test
new file mode 100644
index 0000000..e20b9e2
--- /dev/null
+++ b/test/clangd/initialize-params-invalid.test
@@ -0,0 +1,22 @@
+# RUN: clangd -run-synchronously < %s | FileCheck %s

+# It is absolutely vital that this file has CRLF line endings.

+#

+# Test with invalid initialize request parameters

+Content-Length: 142

+

+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":"","rootUri":"file:///path/to/workspace","capabilities":{},"trace":"off"}}

+# CHECK: Content-Length: 535

+# CHECK: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{

+# CHECK:   "textDocumentSync": 1,

+# CHECK:   "documentFormattingProvider": true,

+# CHECK:   "documentRangeFormattingProvider": true,

+# CHECK:   "documentOnTypeFormattingProvider": {"firstTriggerCharacter":"}","moreTriggerCharacter":[]},

+# CHECK:   "codeActionProvider": true,

+# CHECK:   "completionProvider": {"resolveProvider": false, "triggerCharacters": [".",">",":"]},

+# CHECK:   "signatureHelpProvider": {"triggerCharacters": ["(",","]},

+# CHECK:   "definitionProvider": true

+# CHECK: }}}

+#

+Content-Length: 44

+

+{"jsonrpc":"2.0","id":3,"method":"shutdown"}

diff --git a/test/clangd/initialize-params.test b/test/clangd/initialize-params.test
new file mode 100644
index 0000000..1b91a94
--- /dev/null
+++ b/test/clangd/initialize-params.test
@@ -0,0 +1,22 @@
+# RUN: clangd -run-synchronously < %s | FileCheck %s

+# It is absolutely vital that this file has CRLF line endings.

+#

+# Test initialize request parameters with rootUri

+Content-Length: 143

+

+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootUri":"file:///path/to/workspace","capabilities":{},"trace":"off"}}

+# CHECK: Content-Length: 535

+# CHECK: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{

+# CHECK:   "textDocumentSync": 1,

+# CHECK:   "documentFormattingProvider": true,

+# CHECK:   "documentRangeFormattingProvider": true,

+# CHECK:   "documentOnTypeFormattingProvider": {"firstTriggerCharacter":"}","moreTriggerCharacter":[]},

+# CHECK:   "codeActionProvider": true,

+# CHECK:   "completionProvider": {"resolveProvider": false, "triggerCharacters": [".",">",":"]},

+# CHECK:   "signatureHelpProvider": {"triggerCharacters": ["(",","]},

+# CHECK:   "definitionProvider": true

+# CHECK: }}}

+#

+Content-Length: 44

+

+{"jsonrpc":"2.0","id":3,"method":"shutdown"}

diff --git a/test/clangd/input-mirror.test b/test/clangd/input-mirror.test
new file mode 100644
index 0000000..2071ecc
--- /dev/null
+++ b/test/clangd/input-mirror.test
@@ -0,0 +1,154 @@
+# RUN: clangd -run-synchronously -input-mirror-file %t < %s

+# Note that we have to use '-Z' as -input-mirror-file does not have a newline at the end of file.

+# RUN: diff -b %t %s

+# It is absolutely vital that this file has CRLF line endings.

+#

+Content-Length: 125

+

+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}

+

+Content-Length: 172

+

+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"int main() {\nint a;\na;\n}\n"}}}

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":2,"character":0}}}

+# Go to local variable

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":2,"character":1}}}

+# Go to local variable, end of token

+

+Content-Length: 214

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":2},"contentChanges":[{"text":"struct Foo {\nint x;\n};\nint main() {\n  Foo bar = { x : 1 };\n}\n"}]}}

+

+Content-Length: 149

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":4,"character":14}}}

+# Go to field, GNU old-style field designator 

+

+Content-Length: 215

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":3},"contentChanges":[{"text":"struct Foo {\nint x;\n};\nint main() {\n  Foo baz = { .x = 2 };\n}\n"}]}}

+

+Content-Length: 149

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":4,"character":15}}}

+# Go to field, field designator 

+

+Content-Length: 187

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":4},"contentChanges":[{"text":"int main() {\n   main();\n   return 0;\n}"}]}}

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":1,"character":3}}}

+# Go to function declaration, function call 

+

+Content-Length: 208

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":5},"contentChanges":[{"text":"struct Foo {\n};\nint main() {\n   Foo bar;\n   return 0;\n}\n"}]}}

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":3,"character":3}}}

+# Go to struct declaration, new struct instance 

+

+Content-Length: 231

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":5},"contentChanges":[{"text":"namespace n1 {\nstruct Foo {\n};\n}\nint main() {\n   n1::Foo bar;\n   return 0;\n}\n"}]}}

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":5,"character":4}}}

+# Go to struct declaration, new struct instance, qualified name 

+

+Content-Length: 215

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":6},"contentChanges":[{"text":"struct Foo {\n  int x;\n};\nint main() {\n   Foo bar;\n   bar.x;\n}\n"}]}}

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":5,"character":7}}}

+# Go to field declaration, field reference 

+

+Content-Length: 220

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":7},"contentChanges":[{"text":"struct Foo {\n  void x();\n};\nint main() {\n   Foo bar;\n   bar.x();\n}\n"}]}}

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":5,"character":7}}}

+# Go to method declaration, method call 

+

+Content-Length: 240

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":7},"contentChanges":[{"text":"struct Foo {\n};\ntypedef Foo TypedefFoo;\nint main() {\n   TypedefFoo bar;\n   return 0;\n}\n"}]}}

+

+Content-Length: 149

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":4,"character":10}}}

+# Go to typedef 

+

+Content-Length: 254

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":7},"contentChanges":[{"text":"template <typename MyTemplateParam>\nvoid foo() {\n MyTemplateParam a;\n}\nint main() {\n   return 0;\n}\n"}]}}

+

+Content-Length: 149

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":2,"character":13}}}

+# Go to template type parameter. Fails until clangIndex is modified to handle those.

+# no-CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 0, "character": 10}, "end": {"line": 0, "character": 34}}}]}

+

+Content-Length: 256

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":7},"contentChanges":[{"text":"namespace ns {\nstruct Foo {\nstatic void bar() {}\n};\n}\nint main() {\n   ns::Foo::bar();\n   return 0;\n}\n"}]}}

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":6,"character":4}}}

+# Go to namespace, static method call 

+

+Content-Length: 265

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":7},"contentChanges":[{"text":"namespace ns {\nstruct Foo {\n  int field;\n  Foo(int param) : field(param) {}\n};\n}\nint main() {\n   return 0;\n}\n"}]}}

+

+Content-Length: 149

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":3,"character":21}}}

+# Go to field, member initializer 

+

+Content-Length: 204

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":7},"contentChanges":[{"text":"#define MY_MACRO 0\nint main() {\n  return MY_MACRO;\n}\n"}]}}

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":2,"character":9}}}

+# Go to macro.

+

+Content-Length: 217

+

+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":7},"contentChanges":[{"text":"#define FOO 1\nint a = FOO;\n#define FOO 2\nint b = FOO;\n#undef FOO\n"}]}}

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":1,"character":8}}}

+# Go to macro, re-defined later

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":3,"character":8}}}

+# Go to macro, undefined later

+

+Content-Length: 148

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":4,"character":7}}}

+# Go to macro, being undefined

+

+Content-Length: 44

+

+{"jsonrpc":"2.0","id":3,"method":"shutdown"}

diff --git a/test/clangd/protocol.test b/test/clangd/protocol.test
new file mode 100644
index 0000000..dc36145
--- /dev/null
+++ b/test/clangd/protocol.test
@@ -0,0 +1,82 @@
+# RUN: clangd -run-synchronously < %s | FileCheck %s

+# RUN: clangd -run-synchronously < %s 2>&1 | FileCheck -check-prefix=STDERR %s

+# vim: fileformat=dos

+# It is absolutely vital that this file has CRLF line endings.

+#

+# Test protocol parsing

+Content-Length: 125

+Content-Type: application/vscode-jsonrpc; charset-utf-8

+

+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}

+# Test message with Content-Type after Content-Length

+#

+# CHECK: "jsonrpc":"2.0","id":0,"result":{"capabilities":{

+# CHECK-DAG: "textDocumentSync": 1,

+# CHECK-DAG: "documentFormattingProvider": true,

+# CHECK-DAG: "documentRangeFormattingProvider": true,

+# CHECK-DAG: "documentOnTypeFormattingProvider": {"firstTriggerCharacter":"}","moreTriggerCharacter":[]},

+# CHECK-DAG: "codeActionProvider": true,

+# CHECK-DAG: "completionProvider": {"resolveProvider": false, "triggerCharacters": [".",">",":"]},

+# CHECK-DAG: "definitionProvider": true

+# CHECK: }}

+

+Content-Length: 246

+

+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"struct fake { int a, bb, ccc; int f(int i, const float f) const; };\nint main() {\n  fake f;\n  f.\n}\n"}}}

+

+Content-Type: application/vscode-jsonrpc; charset-utf-8

+Content-Length: 146

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:/main.cpp"},"position":{"line":3,"character":5}}}

+# Test message with Content-Type before Content-Length

+#

+# CHECK: {"jsonrpc":"2.0","id":1,"result":[

+# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"000035a","filterText":"a","insertText":"a","insertTextFormat":1}

+# CHECK: ]}

+

+X-Test: Testing

+Content-Type: application/vscode-jsonrpc; charset-utf-8

+Content-Length: 146

+Content-Type: application/vscode-jsonrpc; charset-utf-8

+X-Testing: Test

+

+{"jsonrpc":"2.0","id":2,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:/main.cpp"},"position":{"line":3,"character":5}}}

+

+Content-Type: application/vscode-jsonrpc; charset-utf-8

+Content-Length: 10

+Content-Length: 146

+

+{"jsonrpc":"2.0","id":3,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:/main.cpp"},"position":{"line":3,"character":5}}}

+# Test message with duplicate Content-Length headers

+#

+# CHECK: {"jsonrpc":"2.0","id":3,"result":[

+# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"000035a","filterText":"a","insertText":"a","insertTextFormat":1}

+# CHECK: ]}

+# STDERR: Warning: Duplicate Content-Length header received. The previous value for this message (10) was ignored.

+

+Content-Type: application/vscode-jsonrpc; charset-utf-8

+Content-Length: 10

+

+{"jsonrpc":"2.0","id":4,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:/main.cpp"},"position":{"line":3,"character":5}}}

+# Test message with malformed Content-Length

+#

+# STDERR: JSON dispatch failed!

+# Ensure we recover by sending another (valid) message

+

+Content-Length: 146

+

+{"jsonrpc":"2.0","id":5,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:/main.cpp"},"position":{"line":3,"character":5}}}

+# Test message with Content-Type before Content-Length

+#

+# CHECK: {"jsonrpc":"2.0","id":5,"result":[

+# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"000035a","filterText":"a","insertText":"a","insertTextFormat":1}

+# CHECK: ]}

+

+Content-Length: 1024

+

+{"jsonrpc":"2.0","id":5,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:/main.cpp"},"position":{"line":3,"character":5}}}

+# Test message which reads beyond the end of the stream.

+#

+# Ensure this is the last test in the file!

+# STDERR: Input was aborted. Read only {{[0-9]+}} bytes of expected {{[0-9]+}}.

+

diff --git a/test/clangd/signature-help.test b/test/clangd/signature-help.test
new file mode 100644
index 0000000..ba4f246
--- /dev/null
+++ b/test/clangd/signature-help.test
@@ -0,0 +1,42 @@
+# RUN: clangd -run-synchronously < %s | FileCheck %s

+# It is absolutely vital that this file has CRLF line endings.

+

+# Start a session.

+Content-Length: 125

+

+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}

+

+# Modify the document.

+Content-Length: 333

+

+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"void foo(int x, int y);\nvoid foo(int x, float y);\nvoid foo(float x, int y);\nvoid foo(float x, float y);\nvoid bar(int x, int y = 0);\nvoid bar(float x = 0, int y = 42);\nint main() { foo("}}}

+

+# Ask for signature help.

+Content-Length: 151

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/signatureHelp","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":8,"character":9}}}

+# CHECK: {"jsonrpc":"2.0","id":1,"result":{"activeSignature":0,"activeParameter":0,"signatures":[

+# CHECK-DAG: {"label":"foo(float x, float y) -> void","parameters":[{"label":"float x"},{"label":"float y"}]}

+# CHECK-DAG: {"label":"foo(float x, int y) -> void","parameters":[{"label":"float x"},{"label":"int y"}]}

+# CHECK-DAG: {"label":"foo(int x, float y) -> void","parameters":[{"label":"int x"},{"label":"float y"}]}

+# CHECK-DAG: {"label":"foo(int x, int y) -> void","parameters":[{"label":"int x"},{"label":"int y"}]}

+# CHECK: ]}

+

+# Modify the document

+Content-Length: 333

+

+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":2,"text":"void foo(int x, int y);\nvoid foo(int x, float y);\nvoid foo(float x, int y);\nvoid foo(float x, float y);\nvoid bar(int x, int y = 0);\nvoid bar(float x = 0, int y = 42);\nint main() { bar("}}}

+

+# Ask for signature help (this checks default argument handling).

+Content-Length: 151

+

+{"jsonrpc":"2.0","id":2,"method":"textDocument/signatureHelp","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":8,"character":9}}}

+# CHECK: {"jsonrpc":"2.0","id":2,"result":{"activeSignature":0,"activeParameter":0,"signatures":[

+# CHECK-DAG: {"label":"bar(int x, int y = 0) -> void","parameters":[{"label":"int x"},{"label":"int y = 0"}]}

+# CHECK-DAG: {"label":"bar(float x = 0, int y = 42) -> void","parameters":[{"label":"float x = 0"},{"label":"int y = 42"}]}

+# CHECK: ]}

+

+# Shutdown.

+Content-Length: 49

+

+{"jsonrpc":"2.0","id":100000,"method":"shutdown"}

diff --git a/test/clangd/unsupported-method.test b/test/clangd/unsupported-method.test
new file mode 100644
index 0000000..200bae0
--- /dev/null
+++ b/test/clangd/unsupported-method.test
@@ -0,0 +1,19 @@
+# RUN: clangd -run-synchronously < %s | FileCheck %s

+# It is absolutely vital that this file has CRLF line endings.

+#

+Content-Length: 125

+

+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}

+

+Content-Length: 143

+

+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":""}}}

+

+Content-Length: 92

+

+{"jsonrpc":"2.0","id":1,"method":"textDocument/jumpInTheAirLikeYouJustDontCare","params":{}}

+# CHECK: {"jsonrpc":"2.0","id":1,"error":{"code":-32601,"message":"method not found"}}

+

+Content-Length: 44

+

+{"jsonrpc":"2.0","id":2,"method":"shutdown"}

diff --git a/test/include-fixer/yamldb_plugin.cpp b/test/include-fixer/yamldb_plugin.cpp
index 8de643e..5b6760a 100644
--- a/test/include-fixer/yamldb_plugin.cpp
+++ b/test/include-fixer/yamldb_plugin.cpp
@@ -1,23 +1,24 @@
+// REQUIRES: static-analyzer
 // RUN: c-index-test -test-load-source-reparse 2 all %s -Xclang -add-plugin -Xclang clang-include-fixer -fspell-checking -Xclang -plugin-arg-clang-include-fixer -Xclang -input=%p/Inputs/fake_yaml_db.yaml 2>&1 | FileCheck %s
 
 foo f;
 foo g;
 unknown u;
 
-// CHECK: yamldb_plugin.cpp:3:1: error: unknown type name 'foo'; did you mean 'foo'?
-// CHECK: Number FIX-ITs = 1
-// CHECK: FIX-IT: Replace [3:1 - 3:4] with "foo"
-// CHECK: yamldb_plugin.cpp:3:1: note: Add '#include "foo.h"' to provide the missing declaration [clang-include-fixer]
-// CHECK: Number FIX-ITs = 1
-// CHECK: FIX-IT: Insert "#include "foo.h"
 // CHECK: yamldb_plugin.cpp:4:1: error: unknown type name 'foo'; did you mean 'foo'?
 // CHECK: Number FIX-ITs = 1
 // CHECK: FIX-IT: Replace [4:1 - 4:4] with "foo"
 // CHECK: yamldb_plugin.cpp:4:1: note: Add '#include "foo.h"' to provide the missing declaration [clang-include-fixer]
 // CHECK: Number FIX-ITs = 1
 // CHECK: FIX-IT: Insert "#include "foo.h"
-// CHECK: " at 3:1
-// CHECK: yamldb_plugin.cpp:5:1:
+// CHECK: yamldb_plugin.cpp:5:1: error: unknown type name 'foo'; did you mean 'foo'?
+// CHECK: Number FIX-ITs = 1
+// CHECK: FIX-IT: Replace [5:1 - 5:4] with "foo"
+// CHECK: yamldb_plugin.cpp:5:1: note: Add '#include "foo.h"' to provide the missing declaration [clang-include-fixer]
+// CHECK: Number FIX-ITs = 1
+// CHECK: FIX-IT: Insert "#include "foo.h"
+// CHECK: " at 4:1
+// CHECK: yamldb_plugin.cpp:6:1:
 // CHECK: error: unknown type name 'unknown'
 // CHECK: Number FIX-ITs = 0
 // CHECK-NOT: error
diff --git a/test/lit.cfg b/test/lit.cfg
index bb59293..3bffbdb 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -54,9 +54,7 @@
 config.test_source_root = os.path.dirname(__file__)
 
 # test_exec_root: The root path where tests should be run.
-clang_tools_binary_dir = getattr(config, 'clang_tools_binary_dir', None)
-if clang_tools_binary_dir is not None:
-    config.test_exec_root = os.path.join(clang_tools_binary_dir, 'test')
+config.test_exec_root = os.path.join(config.clang_tools_binary_dir, 'test')
 
 # Clear some environment variables that might affect Clang.
 #
@@ -88,89 +86,19 @@
     del config.environment[name]
 
 # Tweak the PATH to include the tools dir and the scripts dir.
-if clang_tools_binary_dir is not None:
-    clang_tools_dir = getattr(config, 'clang_tools_dir', None)
-    if not clang_tools_dir:
-        lit_config.fatal('No Clang tools dir set!')
-    llvm_tools_dir = getattr(config, 'llvm_tools_dir', None)
-    if not llvm_tools_dir:
-        lit_config.fatal('No LLVM tools dir set!')
-    path = os.path.pathsep.join((
-            clang_tools_dir, llvm_tools_dir, config.environment['PATH']))
-    config.environment['PATH'] = path
+path = os.path.pathsep.join((
+        config.clang_tools_dir, config.llvm_tools_dir, config.environment['PATH']))
+config.environment['PATH'] = path
 
-    llvm_libs_dir = getattr(config, 'llvm_libs_dir', None)
-    if not llvm_libs_dir:
-        lit_config.fatal('No LLVM libs dir set!')
-    path = os.path.pathsep.join((llvm_libs_dir,
-                                 config.environment.get('LD_LIBRARY_PATH','')))
-    config.environment['LD_LIBRARY_PATH'] = path
-
-###
-
-# Check that the object root is known.
-if config.test_exec_root is None:
-    # Otherwise, we haven't loaded the site specific configuration (the user is
-    # probably trying to run on a test file directly, and either the site
-    # configuration hasn't been created by the build system, or we are in an
-    # out-of-tree build situation).
-
-    # Check for 'clang_site_config' user parameter, and use that if available.
-    site_cfg = lit_config.params.get('clang_tools_extra_site_config', None)
-    if site_cfg and os.path.exists(site_cfg):
-        lit_config.load_config(config, site_cfg)
-        raise SystemExit
-
-    # Try to detect the situation where we are using an out-of-tree build by
-    # looking for 'llvm-config'.
-    #
-    # FIXME: I debated (i.e., wrote and threw away) adding logic to
-    # automagically generate the lit.site.cfg if we are in some kind of fresh
-    # build situation. This means knowing how to invoke the build system though,
-    # and I decided it was too much magic. We should solve this by just having
-    # the .cfg files generated during the configuration step.
-
-    llvm_config = lit.util.which('llvm-config', config.environment['PATH'])
-    if not llvm_config:
-        lit_config.fatal('No site specific configuration available!')
-
-    # Get the source and object roots.
-    llvm_src_root = lit.util.capture(['llvm-config', '--src-root']).strip()
-    llvm_obj_root = lit.util.capture(['llvm-config', '--obj-root']).strip()
-    clang_src_root = os.path.join(llvm_src_root, "tools", "clang")
-    clang_obj_root = os.path.join(llvm_obj_root, "tools", "clang")
-
-    clang_tools_extra_src_root = os.path.join(clang_src_root, "tools", "extra")
-    clang_tools_extra_obj_root = os.path.join(clang_obj_root, "tools", "extra")
-    # Validate that we got a tree which points to here, using the standard
-    # tools/clang layout.
-    this_src_root = os.path.dirname(config.test_source_root)
-    if os.path.realpath(clang_tools_extra_src_root) != os.path.realpath(this_src_root):
-        lit_config.fatal('No site specific configuration available!')
-
-    # Check that the site specific configuration exists.
-    site_cfg = os.path.join(clang_tools_extra_obj_root, 'test', 'lit.site.cfg')
-    if not os.path.exists(site_cfg):
-        lit_config.fatal(
-            'No site specific configuration available! You may need to '
-            'run "make test" in your Clang build directory.')
-
-    # Okay, that worked. Notify the user of the automagic, and reconfigure.
-    lit_config.note('using out-of-tree build at %r' % clang_obj_root)
-    lit_config.load_config(config, site_cfg)
-    raise SystemExit
-
-###
-
-import os
+path = os.path.pathsep.join((config.clang_libs_dir, config.llvm_libs_dir,
+                              config.environment.get('LD_LIBRARY_PATH','')))
+config.environment['LD_LIBRARY_PATH'] = path
 
 # When running under valgrind, we mangle '-vg' onto the end of the triple so we
 # can check it with XFAIL and XTARGET.
 if lit_config.useValgrind:
     config.target_triple += '-vg'
 
-###
-
 # Set available features we allow tests to conditionalize on.
 #
 # As of 2011.08, crash-recovery tests still do not pass on FreeBSD.
@@ -189,13 +117,18 @@
 if platform.system() not in ['Windows']:
     config.available_features.add('ansi-escape-sequences')
 
-check_clang_tidy = os.path.join(
-    config.test_source_root, "clang-tidy", "check_clang_tidy.py")
-config.substitutions.append(
-    ('%check_clang_tidy',
-     '%s %s' % (config.python_executable, check_clang_tidy)) )
-clang_tidy_diff = os.path.join(
-    config.test_source_root, "..", "clang-tidy", "tool", "clang-tidy-diff.py")
-config.substitutions.append(
-    ('%clang_tidy_diff',
-     '%s %s' % (config.python_executable, clang_tidy_diff)) )
+if config.clang_staticanalyzer:
+    config.available_features.add('static-analyzer')
+    check_clang_tidy = os.path.join(
+        config.test_source_root, "clang-tidy", "check_clang_tidy.py")
+    config.substitutions.append(
+        ('%check_clang_tidy',
+         '%s %s' % (config.python_executable, check_clang_tidy)) )
+    clang_tidy_diff = os.path.join(
+        config.test_source_root, "..", "clang-tidy", "tool", "clang-tidy-diff.py")
+    config.substitutions.append(
+        ('%clang_tidy_diff',
+         '%s %s' % (config.python_executable, clang_tidy_diff)) )
+else:
+    # exclude the clang-tidy test directory
+    config.excludes.append('clang-tidy')
diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in
index dfd0164..86e9617 100644
--- a/test/lit.site.cfg.in
+++ b/test/lit.site.cfg.in
@@ -7,8 +7,10 @@
 config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@"
 config.clang_tools_binary_dir = "@CLANG_TOOLS_BINARY_DIR@"
 config.clang_tools_dir = "@CLANG_TOOLS_DIR@"
+config.clang_libs_dir = "@SHLIBDIR@"
 config.python_executable = "@PYTHON_EXECUTABLE@"
 config.target_triple = "@TARGET_TRIPLE@"
+config.clang_staticanalyzer = @CLANG_ENABLE_STATIC_ANALYZER@
 
 # Support substitution of the tools and libs dirs with user parameters. This is
 # used when we can't determine the tool dir at configuration time.
diff --git a/test/pp-trace/pp-trace-conditional.cpp b/test/pp-trace/pp-trace-conditional.cpp
index e3e225f..ac5d3b3 100644
--- a/test/pp-trace/pp-trace-conditional.cpp
+++ b/test/pp-trace/pp-trace-conditional.cpp
@@ -92,7 +92,7 @@
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:7:2"
 // CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:6:2"
 // CHECK-NEXT: - Callback: SourceRangeSkipped
-// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:6:2", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:7:2"]
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:6:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:7:2"]
 // CHECK-NEXT: - Callback: If
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:9:2"
 // CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:9:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:10:1"]
@@ -104,7 +104,7 @@
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:11:2"
 // CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:9:2"
 // CHECK-NEXT: - Callback: SourceRangeSkipped
-// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:10:2", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:11:2"]
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:10:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:11:2"]
 // CHECK-NEXT: - Callback: If
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:13:2"
 // CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:13:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:14:1"]
@@ -113,7 +113,7 @@
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:14:2"
 // CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:13:2"
 // CHECK-NEXT: - Callback: SourceRangeSkipped
-// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:13:2", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:14:2"]
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:13:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:14:2"]
 // CHECK-NEXT: - Callback: Endif
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:15:2"
 // CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:13:2"
@@ -130,7 +130,7 @@
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:19:2"
 // CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:17:2"
 // CHECK-NEXT: - Callback: SourceRangeSkipped
-// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:18:2", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:19:2"]
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:18:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:19:2"]
 // CHECK-NEXT: - Callback: If
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:20:2"
 // CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:20:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:21:1"]
@@ -144,7 +144,7 @@
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:22:2"
 // CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:20:2"
 // CHECK-NEXT: - Callback: SourceRangeSkipped
-// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:21:2", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:22:2"]
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:21:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:22:2"]
 // CHECK-NEXT: - Callback: If
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:24:2"
 // CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:24:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:25:1"]
@@ -155,7 +155,7 @@
 // CHECK-NEXT:   ConditionValue: CVK_True
 // CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:24:2"
 // CHECK-NEXT: - Callback: SourceRangeSkipped
-// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:24:2", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:25:2"]
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:24:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:25:2"]
 // CHECK-NEXT: - Callback: Endif
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:26:2"
 // CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:24:2"
@@ -172,7 +172,7 @@
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:29:2"
 // CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:27:2"
 // CHECK-NEXT: - Callback: SourceRangeSkipped
-// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:27:2", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:29:2"]
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:27:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:29:2"]
 // CHECK-NEXT: - Callback: If
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:30:2"
 // CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:30:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:31:1"]
@@ -186,7 +186,7 @@
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:32:2"
 // CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:30:2"
 // CHECK-NEXT: - Callback: SourceRangeSkipped
-// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:31:2", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:32:2"]
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:31:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:32:2"]
 // CHECK-NEXT: - Callback: If
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:33:2"
 // CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:33:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:34:1"]
@@ -200,7 +200,7 @@
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:35:2"
 // CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:33:2"
 // CHECK-NEXT: - Callback: SourceRangeSkipped
-// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:34:2", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:35:2"]
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:34:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:35:2"]
 // CHECK-NEXT: - Callback: If
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:37:2"
 // CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:37:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:38:1"]
@@ -211,7 +211,7 @@
 // CHECK-NEXT:   ConditionValue: CVK_True
 // CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:37:2"
 // CHECK-NEXT: - Callback: SourceRangeSkipped
-// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:37:2", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:38:2"]
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:37:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:38:2"]
 // CHECK-NEXT: - Callback: Else
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:39:2"
 // CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:37:2"
@@ -219,7 +219,7 @@
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:40:2"
 // CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:37:2"
 // CHECK-NEXT: - Callback: SourceRangeSkipped
-// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:39:2", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:40:2"]
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:39:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:40:2"]
 // CHECK-NEXT: - Callback: If
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:41:2"
 // CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:41:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:42:1"]
@@ -233,7 +233,7 @@
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:43:2"
 // CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:41:2"
 // CHECK-NEXT: - Callback: SourceRangeSkipped
-// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:41:2", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:43:2"]
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:41:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:43:2"]
 // CHECK-NEXT: - Callback: Endif
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:44:2"
 // CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:41:2"
@@ -250,7 +250,7 @@
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:48:2"
 // CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:45:2"
 // CHECK-NEXT: - Callback: SourceRangeSkipped
-// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:46:2", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:48:2"]
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:46:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:48:2"]
 // CHECK-NEXT: - Callback: If
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:49:2"
 // CHECK-NEXT:   ConditionRange: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:49:4", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:50:1"]
@@ -264,7 +264,7 @@
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:52:2"
 // CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:49:2"
 // CHECK-NEXT: - Callback: SourceRangeSkipped
-// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:50:2", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:52:2"]
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:50:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:52:2"]
 // CHECK-NEXT: - Callback: MacroDefined
 // CHECK-NEXT:   MacroNameTok: MACRO
 // CHECK-NEXT:   MacroDirective: MD_Define
@@ -283,7 +283,7 @@
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:58:2"
 // CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:57:2"
 // CHECK-NEXT: - Callback: SourceRangeSkipped
-// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:57:2", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:58:2"]
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:57:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:58:2"]
 // CHECK-NEXT: - Callback: Ifndef
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:59:2"
 // CHECK-NEXT:   MacroNameTok: MACRO
@@ -292,7 +292,7 @@
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:60:2"
 // CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:59:2"
 // CHECK-NEXT: - Callback: SourceRangeSkipped
-// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:59:2", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:60:2"]
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-conditional.cpp:59:1", "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:60:2"]
 // CHECK-NEXT: - Callback: Ifndef
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-conditional.cpp:61:2"
 // CHECK-NEXT:   MacroNameTok: NO_MACRO
diff --git a/test/pp-trace/pp-trace-macro.cpp b/test/pp-trace/pp-trace-macro.cpp
index 85e2088..e6ba761 100644
--- a/test/pp-trace/pp-trace-macro.cpp
+++ b/test/pp-trace/pp-trace-macro.cpp
@@ -64,7 +64,7 @@
 // CHECK-NEXT:   Loc: "{{.*}}{{[/\\]}}pp-trace-macro.cpp:9:2"
 // CHECK-NEXT:   IfLoc: "{{.*}}{{[/\\]}}pp-trace-macro.cpp:8:2"
 // CHECK-NEXT: - Callback: SourceRangeSkipped
-// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-macro.cpp:8:2", "{{.*}}{{[/\\]}}pp-trace-macro.cpp:9:2"]
+// CHECK-NEXT:   Range: ["{{.*}}{{[/\\]}}pp-trace-macro.cpp:8:1", "{{.*}}{{[/\\]}}pp-trace-macro.cpp:9:2"]
 // CHECK-NEXT: - Callback: MacroDefined
 // CHECK-NEXT:   MacroNameTok: FUNCMACRO
 // CHECK-NEXT:   MacroDirective: MD_Define
diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt
index f7ee0fc..385759d 100644
--- a/unittests/CMakeLists.txt
+++ b/unittests/CMakeLists.txt
@@ -9,7 +9,8 @@
 add_subdirectory(clang-apply-replacements)
 add_subdirectory(clang-move)
 add_subdirectory(clang-query)
-add_subdirectory(clang-tidy)
-add_subdirectory(clang-rename)
+if(CLANG_ENABLE_STATIC_ANALYZER)
+  add_subdirectory(clang-tidy)
+endif()
 add_subdirectory(clangd)
 add_subdirectory(include-fixer)
diff --git a/unittests/change-namespace/ChangeNamespaceTests.cpp b/unittests/change-namespace/ChangeNamespaceTests.cpp
index dc8eeb7..c16d864 100644
--- a/unittests/change-namespace/ChangeNamespaceTests.cpp
+++ b/unittests/change-namespace/ChangeNamespaceTests.cpp
@@ -2093,6 +2093,68 @@
   EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
 }
 
+TEST_F(ChangeNamespaceTest, DefaultMoveConstructors) {
+  std::string Code = "namespace na {\n"
+                     "class B {\n"
+                     " public:\n"
+                     "  B() = default;\n"
+                     "  // Allow move only.\n"
+                     "  B(B&&) = default;\n"
+                     "  B& operator=(B&&) = default;\n"
+                     "  B(const B&) = delete;\n"
+                     "  B& operator=(const B&) = delete;\n"
+                     " private:\n"
+                     "  int ref_;\n"
+                     "};\n"
+                     "} // namespace na\n"
+                     "namespace na {\n"
+                     "namespace nb {\n"
+                     "class A {\n"
+                     "public:\n"
+                     "  A() = default;\n"
+                     "  A(A&&) = default;\n"
+                     "  A& operator=(A&&) = default;\n"
+                     "private:\n"
+                     "  B b;\n"
+                     "  A(const A&) = delete;\n"
+                     "  A& operator=(const A&) = delete;\n"
+                     "};\n"
+                     "void f() { A a; a = A(); A aa = A(); }\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+  std::string Expected = "namespace na {\n"
+                         "class B {\n"
+                         " public:\n"
+                         "  B() = default;\n"
+                         "  // Allow move only.\n"
+                         "  B(B&&) = default;\n"
+                         "  B& operator=(B&&) = default;\n"
+                         "  B(const B&) = delete;\n"
+                         "  B& operator=(const B&) = delete;\n"
+                         " private:\n"
+                         "  int ref_;\n"
+                         "};\n"
+                         "} // namespace na\n"
+                         "\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "class A {\n"
+                         "public:\n"
+                         "  A() = default;\n"
+                         "  A(A&&) = default;\n"
+                         "  A& operator=(A&&) = default;\n"
+                         "private:\n"
+                         "  na::B b;\n"
+                         "  A(const A&) = delete;\n"
+                         "  A& operator=(const A&) = delete;\n"
+                         "};\n"
+                         "void f() { A a; a = A(); A aa = A(); }\n"
+                         "} // namespace y\n"
+                         "} // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+
 } // anonymous namespace
 } // namespace change_namespace
 } // namespace clang
diff --git a/unittests/clang-apply-replacements/ApplyReplacementsTest.cpp b/unittests/clang-apply-replacements/ApplyReplacementsTest.cpp
new file mode 100644
index 0000000..39f5b6f
--- /dev/null
+++ b/unittests/clang-apply-replacements/ApplyReplacementsTest.cpp
@@ -0,0 +1,53 @@
+//===- clang-apply-replacements/ApplyReplacementsTest.cpp
+//----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang-apply-replacements/Tooling/ApplyReplacements.h"
+#include "gtest/gtest.h"
+
+using namespace clang::replace;
+using namespace llvm;
+
+namespace clang {
+namespace tooling {
+
+static TUDiagnostics
+makeTUDiagnostics(const std::string &MainSourceFile, StringRef DiagnosticName,
+                  const DiagnosticMessage &Message,
+                  const StringMap<Replacements> &Replacements,
+                  StringRef BuildDirectory) {
+  TUDiagnostics TUs;
+  TUs.push_back({MainSourceFile,
+                 {{DiagnosticName,
+                   Message,
+                   Replacements,
+                   {},
+                   Diagnostic::Warning,
+                   BuildDirectory}}});
+  return TUs;
+}
+
+// Test to ensure diagnostics with no fixes, will be merged correctly
+// before applying.
+TEST(ApplyReplacementsTest, mergeDiagnosticsWithNoFixes) {
+  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts(new DiagnosticOptions());
+  DiagnosticsEngine Diagnostics(
+      IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), DiagOpts.get());
+  FileManager Files((FileSystemOptions()));
+  SourceManager SM(Diagnostics, Files);
+  TUDiagnostics TUs =
+      makeTUDiagnostics("path/to/source.cpp", "diagnostic", {}, {}, "path/to");
+  FileToReplacementsMap ReplacementsMap;
+
+  EXPECT_TRUE(mergeAndDeduplicate(TUs, ReplacementsMap, SM));
+  EXPECT_TRUE(ReplacementsMap.empty());
+}
+
+} // end namespace tooling
+} // end namespace clang
diff --git a/unittests/clang-apply-replacements/CMakeLists.txt b/unittests/clang-apply-replacements/CMakeLists.txt
index 3f8fa70..f06dae6 100644
--- a/unittests/clang-apply-replacements/CMakeLists.txt
+++ b/unittests/clang-apply-replacements/CMakeLists.txt
@@ -8,10 +8,12 @@
   )
 
 add_extra_unittest(ClangApplyReplacementsTests
+  ApplyReplacementsTest.cpp
   ReformattingTest.cpp
   )
 
 target_link_libraries(ClangApplyReplacementsTests
   clangApplyReplacements
+  clangBasic
   clangToolingCore
   )
diff --git a/unittests/clang-rename/CMakeLists.txt b/unittests/clang-rename/CMakeLists.txt
deleted file mode 100644
index a121fdc..0000000
--- a/unittests/clang-rename/CMakeLists.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-set(LLVM_LINK_COMPONENTS
-  support
-  )
-
-get_filename_component(CLANG_RENAME_SOURCE_DIR
-  ${CMAKE_CURRENT_SOURCE_DIR}/../../clang-rename REALPATH)
-include_directories(
-  ${CLANG_RENAME_SOURCE_DIR}
-  )
-
-# We'd like clang/unittests/Tooling/RewriterTestContext.h in the test.
-include_directories(${CLANG_SOURCE_DIR})
-
-add_extra_unittest(ClangRenameTests
-  RenameClassTest.cpp
-  )
-
-target_link_libraries(ClangRenameTests
-  clangAST
-  clangASTMatchers
-  clangBasic
-  clangFormat
-  clangFrontend
-  clangRename
-  clangRewrite
-  clangTooling
-  clangToolingCore
-  )
diff --git a/unittests/clang-rename/ClangRenameTest.h b/unittests/clang-rename/ClangRenameTest.h
deleted file mode 100644
index 543b47b..0000000
--- a/unittests/clang-rename/ClangRenameTest.h
+++ /dev/null
@@ -1,112 +0,0 @@
-//===-- ClangRenameTests.cpp - clang-rename unit tests --------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "RenamingAction.h"
-#include "USRFindingAction.h"
-#include "unittests/Tooling/RewriterTestContext.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/FileSystemOptions.h"
-#include "clang/Basic/VirtualFileSystem.h"
-#include "clang/Format/Format.h"
-#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Frontend/PCHContainerOperations.h"
-#include "clang/Tooling/Refactoring.h"
-#include "clang/Tooling/Tooling.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "gtest/gtest.h"
-#include <memory>
-#include <string>
-#include <vector>
-
-namespace clang {
-namespace clang_rename {
-namespace test {
-
-struct Case {
-  std::string Before;
-  std::string After;
-  std::string OldName;
-  std::string NewName;
-};
-
-class ClangRenameTest : public testing::Test,
-                        public testing::WithParamInterface<Case> {
-protected:
-  void AppendToHeader(StringRef Code) { HeaderContent += Code.str(); }
-
-  std::string runClangRenameOnCode(llvm::StringRef Code,
-                                   llvm::StringRef OldName,
-                                   llvm::StringRef NewName) {
-    std::string NewCode;
-    llvm::raw_string_ostream(NewCode) << llvm::format(
-        "#include \"%s\"\n%s", HeaderName.c_str(), Code.str().c_str());
-    tooling::FileContentMappings FileContents = {{HeaderName, HeaderContent},
-                                                 {CCName, NewCode}};
-    clang::RewriterTestContext Context;
-    Context.createInMemoryFile(HeaderName, HeaderContent);
-    clang::FileID InputFileID = Context.createInMemoryFile(CCName, NewCode);
-
-    rename::USRFindingAction FindingAction({}, {OldName}, false);
-    std::unique_ptr<tooling::FrontendActionFactory> USRFindingActionFactory =
-        tooling::newFrontendActionFactory(&FindingAction);
-
-    if (!tooling::runToolOnCodeWithArgs(
-            USRFindingActionFactory->create(), NewCode, {"-std=c++11"}, CCName,
-            "clang-rename", std::make_shared<PCHContainerOperations>(),
-            FileContents))
-      return "";
-
-    const std::vector<std::vector<std::string>> &USRList =
-        FindingAction.getUSRList();
-    std::vector<std::string> NewNames = {NewName};
-    std::map<std::string, tooling::Replacements> FileToReplacements;
-    rename::QualifiedRenamingAction RenameAction(NewNames, USRList,
-                                                 FileToReplacements);
-    auto RenameActionFactory = tooling::newFrontendActionFactory(&RenameAction);
-    if (!tooling::runToolOnCodeWithArgs(
-            RenameActionFactory->create(), NewCode, {"-std=c++11"}, CCName,
-            "clang-rename", std::make_shared<PCHContainerOperations>(),
-            FileContents))
-      return "";
-
-    formatAndApplyAllReplacements(FileToReplacements, Context.Rewrite, "llvm");
-    return Context.getRewrittenText(InputFileID);
-  }
-
-  void CompareSnippets(StringRef Expected, StringRef Actual) {
-    std::string ExpectedCode;
-    llvm::raw_string_ostream(ExpectedCode) << llvm::format(
-        "#include \"%s\"\n%s", HeaderName.c_str(), Expected.str().c_str());
-    EXPECT_EQ(format(ExpectedCode), format(Actual));
-  }
-
-  std::string format(llvm::StringRef Code) {
-    tooling::Replacements Replaces = format::reformat(
-        format::getLLVMStyle(), Code, {tooling::Range(0, Code.size())});
-    auto ChangedCode = tooling::applyAllReplacements(Code, Replaces);
-    EXPECT_TRUE(static_cast<bool>(ChangedCode));
-    if (!ChangedCode) {
-      llvm::errs() << llvm::toString(ChangedCode.takeError());
-      return "";
-    }
-    return *ChangedCode;
-  }
-
-  std::string HeaderContent;
-  std::string HeaderName = "header.h";
-  std::string CCName = "input.cc";
-};
-
-} // namespace test
-} // namespace clang_rename
-} // namesdpace clang
diff --git a/unittests/clang-rename/RenameClassTest.cpp b/unittests/clang-rename/RenameClassTest.cpp
deleted file mode 100644
index 29b4594..0000000
--- a/unittests/clang-rename/RenameClassTest.cpp
+++ /dev/null
@@ -1,684 +0,0 @@
-//===-- RenameClassTest.cpp - unit tests for renaming classes -------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ClangRenameTest.h"
-
-namespace clang {
-namespace clang_rename {
-namespace test {
-namespace {
-
-class RenameClassTest : public ClangRenameTest {
-public:
-  RenameClassTest() {
-    AppendToHeader(R"(
-      namespace a {
-        class Foo {
-          public:
-            struct Nested {
-              enum NestedEnum {E1, E2};
-            };
-            void func() {}
-          static int Constant;
-        };
-        class Goo {
-          public:
-            struct Nested {
-              enum NestedEnum {E1, E2};
-            };
-        };
-        int Foo::Constant = 1;
-      } // namespace a
-      namespace b {
-      class Foo {};
-      } // namespace b
-
-      #define MACRO(x) x
-
-      template<typename T> class ptr {};
-    )");
-  }
-};
-
-INSTANTIATE_TEST_CASE_P(
-    RenameClassTests, RenameClassTest,
-    testing::ValuesIn(std::vector<Case>({
-        // basic classes
-        {"a::Foo f;", "b::Bar f;", "", ""},
-        {"void f(a::Foo f) {}", "void f(b::Bar f) {}", "", ""},
-        {"void f(a::Foo *f) {}", "void f(b::Bar *f) {}", "", ""},
-        {"a::Foo f() { return a::Foo(); }", "b::Bar f() { return b::Bar(); }",
-         "", ""},
-        {"namespace a {a::Foo f() { return Foo(); }}",
-         "namespace a {b::Bar f() { return b::Bar(); }}", "", ""},
-        {"void f(const a::Foo& a1) {}", "void f(const b::Bar& a1) {}", "", ""},
-        {"void f(const a::Foo* a1) {}", "void f(const b::Bar* a1) {}", "", ""},
-        {"namespace a { void f(Foo a1) {} }",
-         "namespace a { void f(b::Bar a1) {} }", "", ""},
-        {"void f(MACRO(a::Foo) a1) {}", "void f(MACRO(b::Bar) a1) {}", "", ""},
-        {"void f(MACRO(a::Foo a1)) {}", "void f(MACRO(b::Bar a1)) {}", "", ""},
-        {"a::Foo::Nested ns;", "b::Bar::Nested ns;", "", ""},
-        {"auto t = a::Foo::Constant;", "auto t = b::Bar::Constant;", "", ""},
-        {"a::Foo::Nested ns;", "a::Foo::Nested2 ns;", "a::Foo::Nested",
-         "a::Foo::Nested2"},
-
-        // use namespace and typedefs
-        {"using a::Foo; Foo gA;", "using b::Bar; b::Bar gA;", "", ""},
-        {"using a::Foo; void f(Foo gA) {}", "using b::Bar; void f(Bar gA) {}",
-         "", ""},
-        {"using a::Foo; namespace x { Foo gA; }",
-         "using b::Bar; namespace x { Bar gA; }", "", ""},
-        {"struct S { using T = a::Foo; T a_; };",
-         "struct S { using T = b::Bar; T a_; };", "", ""},
-        {"using T = a::Foo; T gA;", "using T = b::Bar; T gA;", "", ""},
-        {"typedef a::Foo T; T gA;", "typedef b::Bar T; T gA;", "", ""},
-        {"typedef MACRO(a::Foo) T; T gA;", "typedef MACRO(b::Bar) T; T gA;", "",
-         ""},
-
-        // struct members and other oddities
-        {"struct S : public a::Foo {};", "struct S : public b::Bar {};", "",
-         ""},
-        {"struct F { void f(a::Foo a1) {} };",
-         "struct F { void f(b::Bar a1) {} };", "", ""},
-        {"struct F { a::Foo a_; };", "struct F { b::Bar a_; };", "", ""},
-        {"struct F { ptr<a::Foo> a_; };", "struct F { ptr<b::Bar> a_; };", "",
-         ""},
-
-        {"void f() { a::Foo::Nested ne; }", "void f() { b::Bar::Nested ne; }",
-         "", ""},
-        {"void f() { a::Goo::Nested ne; }", "void f() { a::Goo::Nested ne; }",
-         "", ""},
-        {"void f() { a::Foo::Nested::NestedEnum e; }",
-         "void f() { b::Bar::Nested::NestedEnum e; }", "", ""},
-        {"void f() { auto e = a::Foo::Nested::NestedEnum::E1; }",
-         "void f() { auto e = b::Bar::Nested::NestedEnum::E1; }", "", ""},
-        {"void f() { auto e = a::Foo::Nested::E1; }",
-         "void f() { auto e = b::Bar::Nested::E1; }", "", ""},
-
-        // templates
-        {"template <typename T> struct Foo { T t; };\n"
-         "void f() { Foo<a::Foo> foo; }",
-         "template <typename T> struct Foo { T t; };\n"
-         "void f() { Foo<b::Bar> foo; }",
-         "", ""},
-        {"template <typename T> struct Foo { a::Foo a; };",
-         "template <typename T> struct Foo { b::Bar a; };", "", ""},
-        {"template <typename T> void f(T t) {}\n"
-         "void g() { f<a::Foo>(a::Foo()); }",
-         "template <typename T> void f(T t) {}\n"
-         "void g() { f<b::Bar>(b::Bar()); }",
-         "", ""},
-        {"template <typename T> int f() { return 1; }\n"
-         "template <> int f<a::Foo>() { return 2; }\n"
-         "int g() { return f<a::Foo>(); }",
-         "template <typename T> int f() { return 1; }\n"
-         "template <> int f<b::Bar>() { return 2; }\n"
-         "int g() { return f<b::Bar>(); }",
-         "", ""},
-        {"struct Foo { template <typename T> T foo(); };\n"
-         "void g() { Foo f;  auto a = f.template foo<a::Foo>(); }",
-         "struct Foo { template <typename T> T foo(); };\n"
-         "void g() { Foo f;  auto a = f.template foo<b::Bar>(); }",
-         "", ""},
-
-        // The following two templates are distilled from regressions found in
-        // unique_ptr<> and type_traits.h
-        {"template <typename T> struct outer {\n"
-         "     typedef T type;\n"
-         "     type Baz();\n"
-         "    };\n"
-         "    outer<a::Foo> g_A;",
-         "template <typename T> struct outer {\n"
-         "      typedef T type;\n"
-         "      type Baz();\n"
-         "    };\n"
-         "    outer<b::Bar> g_A;",
-         "", ""},
-        {"template <typename T> struct nested { typedef T type; };\n"
-         "template <typename T> struct outer { typename nested<T>::type Foo(); "
-         "};\n"
-         "outer<a::Foo> g_A;",
-         "template <typename T> struct nested { typedef T type; };\n"
-         "template <typename T> struct outer { typename nested<T>::type Foo(); "
-         "};\n"
-         "outer<b::Bar> g_A;",
-         "", ""},
-
-        // macros
-        {"#define FOO(T, t) T t\n"
-         "void f() { FOO(a::Foo, a1); FOO(a::Foo, a2); }",
-         "#define FOO(T, t) T t\n"
-         "void f() { FOO(b::Bar, a1); FOO(b::Bar, a2); }",
-         "", ""},
-        {"#define FOO(n) a::Foo n\n"
-         " void f() { FOO(a1); FOO(a2); }",
-         "#define FOO(n) b::Bar n\n"
-         " void f() { FOO(a1); FOO(a2); }",
-         "", ""},
-
-        // Pointer to member functions
-        {"auto gA = &a::Foo::func;", "auto gA = &b::Bar::func;", "", ""},
-        {"using a::Foo; auto gA = &Foo::func;",
-         "using b::Bar; auto gA = &b::Bar::func;", "", ""},
-        {"using a::Foo; namespace x { auto gA = &Foo::func; }",
-         "using b::Bar; namespace x { auto gA = &Bar::func; }", "", ""},
-        {"typedef a::Foo T; auto gA = &T::func;",
-         "typedef b::Bar T; auto gA = &T::func;", "", ""},
-        {"auto gA = &MACRO(a::Foo)::func;", "auto gA = &MACRO(b::Bar)::func;",
-         "", ""},
-
-        // Short match inside a namespace
-        {"namespace a { void f(Foo a1) {} }",
-         "namespace a { void f(b::Bar a1) {} }", "", ""},
-
-        // Correct match.
-        {"using a::Foo; struct F { ptr<Foo> a_; };",
-         "using b::Bar; struct F { ptr<Bar> a_; };", "", ""},
-
-        // avoid false positives
-        {"void f(b::Foo a) {}", "void f(b::Foo a) {}", "", ""},
-        {"namespace b { void f(Foo a) {} }", "namespace b { void f(Foo a) {} }",
-         "", ""},
-
-        // friends, everyone needs friends.
-        {"class Foo { int i; friend class a::Foo; };",
-         "class Foo { int i; friend class b::Bar; };", "", ""},
-    })), );
-
-TEST_P(RenameClassTest, RenameClasses) {
-  auto Param = GetParam();
-  std::string OldName = Param.OldName.empty() ? "a::Foo" : Param.OldName;
-  std::string NewName = Param.NewName.empty() ? "b::Bar" : Param.NewName;
-  std::string Actual = runClangRenameOnCode(Param.Before, OldName, NewName);
-  CompareSnippets(Param.After, Actual);
-}
-
-class NamespaceDetectionTest : public ClangRenameTest {
-protected:
-  NamespaceDetectionTest() {
-    AppendToHeader(R"(
-         class Old {};
-         namespace o1 {
-         class Old {};
-         namespace o2 {
-         class Old {};
-         namespace o3 {
-         class Old {};
-         }  // namespace o3
-         }  // namespace o2
-         }  // namespace o1
-     )");
-  }
-};
-
-INSTANTIATE_TEST_CASE_P(
-    RenameClassTest, NamespaceDetectionTest,
-    ::testing::ValuesIn(std::vector<Case>({
-        // Test old and new namespace overlap.
-        {"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }",
-         "namespace o1 { namespace o2 { namespace o3 { New moo; } } }",
-         "o1::o2::o3::Old", "o1::o2::o3::New"},
-        {"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }",
-         "namespace o1 { namespace o2 { namespace o3 { n3::New moo; } } }",
-         "o1::o2::o3::Old", "o1::o2::n3::New"},
-        {"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }",
-         "namespace o1 { namespace o2 { namespace o3 { n2::n3::New moo; } } }",
-         "o1::o2::o3::Old", "o1::n2::n3::New"},
-        {"namespace o1 { namespace o2 { Old moo; } }",
-         "namespace o1 { namespace o2 { New moo; } }", "::o1::o2::Old",
-         "::o1::o2::New"},
-        {"namespace o1 { namespace o2 { Old moo; } }",
-         "namespace o1 { namespace o2 { n2::New moo; } }", "::o1::o2::Old",
-         "::o1::n2::New"},
-        {"namespace o1 { namespace o2 { Old moo; } }",
-         "namespace o1 { namespace o2 { ::n1::n2::New moo; } }",
-         "::o1::o2::Old", "::n1::n2::New"},
-        {"namespace o1 { namespace o2 { Old moo; } }",
-         "namespace o1 { namespace o2 { n1::n2::New moo; } }", "::o1::o2::Old",
-         "n1::n2::New"},
-
-        // Test old and new namespace with differing depths.
-        {"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }",
-         "namespace o1 { namespace o2 { namespace o3 { New moo; } } }",
-         "o1::o2::o3::Old", "::o1::New"},
-        {"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }",
-         "namespace o1 { namespace o2 { namespace o3 { New moo; } } }",
-         "o1::o2::o3::Old", "::o1::o2::New"},
-        {"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }",
-         "namespace o1 { namespace o2 { namespace o3 { New moo; } } }",
-         "o1::o2::o3::Old", "o1::New"},
-        {"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }",
-         "namespace o1 { namespace o2 { namespace o3 { New moo; } } }",
-         "o1::o2::o3::Old", "o1::o2::New"},
-        {"Old moo;", "o1::New moo;", "::Old", "o1::New"},
-        {"Old moo;", "o1::New moo;", "Old", "o1::New"},
-        {"namespace o1 { ::Old moo; }", "namespace o1 { New moo; }", "Old",
-         "o1::New"},
-        {"namespace o1 { namespace o2 {  Old moo; } }",
-         "namespace o1 { namespace o2 {  ::New moo; } }", "::o1::o2::Old",
-         "::New"},
-        {"namespace o1 { namespace o2 {  Old moo; } }",
-         "namespace o1 { namespace o2 {  New moo; } }", "::o1::o2::Old", "New"},
-
-        // Test moving into the new namespace at different levels.
-        {"namespace n1 { namespace n2 { o1::o2::Old moo; } }",
-         "namespace n1 { namespace n2 { New moo; } }", "::o1::o2::Old",
-         "::n1::n2::New"},
-        {"namespace n1 { namespace n2 { o1::o2::Old moo; } }",
-         "namespace n1 { namespace n2 { New moo; } }", "::o1::o2::Old",
-         "n1::n2::New"},
-        {"namespace n1 { namespace n2 { o1::o2::Old moo; } }",
-         "namespace n1 { namespace n2 { o2::New moo; } }", "::o1::o2::Old",
-         "::n1::o2::New"},
-        {"namespace n1 { namespace n2 { o1::o2::Old moo; } }",
-         "namespace n1 { namespace n2 { o2::New moo; } }", "::o1::o2::Old",
-         "n1::o2::New"},
-        {"namespace n1 { namespace n2 { o1::o2::Old moo; } }",
-         "namespace n1 { namespace n2 { ::o1::o2::New moo; } }",
-         "::o1::o2::Old", "::o1::o2::New"},
-        {"namespace n1 { namespace n2 { o1::o2::Old moo; } }",
-         "namespace n1 { namespace n2 { o1::o2::New moo; } }", "::o1::o2::Old",
-         "o1::o2::New"},
-
-        // Test friends declarations.
-        {"class Foo { friend class o1::Old; };",
-         "class Foo { friend class o1::New; };", "o1::Old", "o1::New"},
-        {"class Foo { int i; friend class o1::Old; };",
-         "class Foo { int i; friend class ::o1::New; };", "::o1::Old",
-         "::o1::New"},
-        {"namespace o1 { class Foo { int i; friend class Old; }; }",
-         "namespace o1 { class Foo { int i; friend class New; }; }", "o1::Old",
-         "o1::New"},
-        {"namespace o1 { class Foo { int i; friend class Old; }; }",
-         "namespace o1 { class Foo { int i; friend class New; }; }",
-         "::o1::Old", "::o1::New"},
-    })), );
-
-TEST_P(NamespaceDetectionTest, RenameClasses) {
-  auto Param = GetParam();
-  std::string Actual =
-      runClangRenameOnCode(Param.Before, Param.OldName, Param.NewName);
-  CompareSnippets(Param.After, Actual);
-}
-
-class TemplatedClassRenameTest : public ClangRenameTest {
-protected:
-  TemplatedClassRenameTest() {
-    AppendToHeader(R"(
-           template <typename T> struct Old {
-             T t_;
-             T f() { return T(); };
-             static T s(T t) { return t; }
-           };
-           namespace ns {
-           template <typename T> struct Old {
-             T t_;
-             T f() { return T(); };
-             static T s(T t) { return t; }
-           };
-           }  // namespace ns
-
-           namespace o1 {
-           namespace o2 {
-           namespace o3 {
-           template <typename T> struct Old {
-             T t_;
-             T f() { return T(); };
-             static T s(T t) { return t; }
-           };
-           }  // namespace o3
-           }  // namespace o2
-           }  // namespace o1
-       )");
-  }
-};
-
-INSTANTIATE_TEST_CASE_P(
-    RenameClassTests, TemplatedClassRenameTest,
-    ::testing::ValuesIn(std::vector<Case>({
-        {"Old<int> gI; Old<bool> gB;", "New<int> gI; New<bool> gB;", "Old",
-         "New"},
-        {"ns::Old<int> gI; ns::Old<bool> gB;",
-         "ns::New<int> gI; ns::New<bool> gB;", "ns::Old", "ns::New"},
-        {"auto gI = &Old<int>::f; auto gB = &Old<bool>::f;",
-         "auto gI = &New<int>::f; auto gB = &New<bool>::f;", "Old", "New"},
-        {"auto gI = &ns::Old<int>::f;", "auto gI = &ns::New<int>::f;",
-         "ns::Old", "ns::New"},
-
-        {"int gI = Old<int>::s(0); bool gB = Old<bool>::s(false);",
-         "int gI = New<int>::s(0); bool gB = New<bool>::s(false);", "Old",
-         "New"},
-        {"int gI = ns::Old<int>::s(0); bool gB = ns::Old<bool>::s(false);",
-         "int gI = ns::New<int>::s(0); bool gB = ns::New<bool>::s(false);",
-         "ns::Old", "ns::New"},
-
-        {"struct S { Old<int*> o_; };", "struct S { New<int*> o_; };", "Old",
-         "New"},
-        {"struct S { ns::Old<int*> o_; };", "struct S { ns::New<int*> o_; };",
-         "ns::Old", "ns::New"},
-
-        {"auto a = reinterpret_cast<Old<int>*>(new Old<int>);",
-         "auto a = reinterpret_cast<New<int>*>(new New<int>);", "Old", "New"},
-        {"auto a = reinterpret_cast<ns::Old<int>*>(new ns::Old<int>);",
-         "auto a = reinterpret_cast<ns::New<int>*>(new ns::New<int>);",
-         "ns::Old", "ns::New"},
-        {"auto a = reinterpret_cast<const Old<int>*>(new Old<int>);",
-         "auto a = reinterpret_cast<const New<int>*>(new New<int>);", "Old",
-         "New"},
-        {"auto a = reinterpret_cast<const ns::Old<int>*>(new ns::Old<int>);",
-         "auto a = reinterpret_cast<const ns::New<int>*>(new ns::New<int>);",
-         "ns::Old", "ns::New"},
-
-        {"Old<bool>& foo();", "New<bool>& foo();", "Old", "New"},
-        {"ns::Old<bool>& foo();", "ns::New<bool>& foo();", "ns::Old",
-         "ns::New"},
-        {"o1::o2::o3::Old<bool>& foo();", "o1::o2::o3::New<bool>& foo();",
-         "o1::o2::o3::Old", "o1::o2::o3::New"},
-        {"namespace ns { Old<bool>& foo(); }",
-         "namespace ns { New<bool>& foo(); }", "ns::Old", "ns::New"},
-        {"const Old<bool>& foo();", "const New<bool>& foo();", "Old", "New"},
-        {"const ns::Old<bool>& foo();", "const ns::New<bool>& foo();",
-         "ns::Old", "ns::New"},
-
-        // FIXME: figure out why this only works when Moo gets
-        // specialized at some point.
-        {"template <typename T> struct Moo { Old<T> o_; }; Moo<int> m;",
-         "template <typename T> struct Moo { New<T> o_; }; Moo<int> m;", "Old",
-         "New"},
-        {"template <typename T> struct Moo { ns::Old<T> o_; }; Moo<int> m;",
-         "template <typename T> struct Moo { ns::New<T> o_; }; Moo<int> m;",
-         "ns::Old", "ns::New"},
-    })), );
-
-TEST_P(TemplatedClassRenameTest, RenameTemplateClasses) {
-  auto Param = GetParam();
-  std::string Actual =
-      runClangRenameOnCode(Param.Before, Param.OldName, Param.NewName);
-  CompareSnippets(Param.After, Actual);
-}
-
-TEST_F(ClangRenameTest, RenameClassWithOutOfLineMembers) {
-  std::string Before = R"(
-      class Old {
-       public:
-        Old();
-        ~Old();
-
-        Old* next();
-
-       private:
-        Old* next_;
-      };
-
-      Old::Old() {}
-      Old::~Old() {}
-      Old* Old::next() { return next_; }
-    )";
-  std::string Expected = R"(
-      class New {
-       public:
-        New();
-        ~New();
-
-        New* next();
-
-       private:
-        New* next_;
-      };
-
-      New::New() {}
-      New::~New() {}
-      New* New::next() { return next_; }
-    )";
-  std::string After = runClangRenameOnCode(Before, "Old", "New");
-  CompareSnippets(Expected, After);
-}
-
-TEST_F(ClangRenameTest, RenameClassWithInlineMembers) {
-  std::string Before = R"(
-      class Old {
-       public:
-        Old() {}
-        ~Old() {}
-
-        Old* next() { return next_; }
-
-       private:
-        Old* next_;
-      };
-    )";
-  std::string Expected = R"(
-      class New {
-       public:
-        New() {}
-        ~New() {}
-
-        New* next() { return next_; }
-
-       private:
-        New* next_;
-      };
-    )";
-  std::string After = runClangRenameOnCode(Before, "Old", "New");
-  CompareSnippets(Expected, After);
-}
-
-// FIXME: no prefix qualifiers being added to the class definition and
-// constructor.
-TEST_F(ClangRenameTest, RenameClassWithNamespaceWithInlineMembers) {
-  std::string Before = R"(
-      namespace ns {
-      class Old {
-       public:
-        Old() {}
-        ~Old() {}
-
-        Old* next() { return next_; }
-
-       private:
-        Old* next_;
-      };
-      }  // namespace ns
-    )";
-  std::string Expected = R"(
-      namespace ns {
-      class ns::New {
-       public:
-        ns::New() {}
-        ~New() {}
-
-        New* next() { return next_; }
-
-       private:
-        New* next_;
-      };
-      }  // namespace ns
-    )";
-  std::string After = runClangRenameOnCode(Before, "ns::Old", "ns::New");
-  CompareSnippets(Expected, After);
-}
-
-// FIXME: no prefix qualifiers being added to the class definition and
-// constructor.
-TEST_F(ClangRenameTest, RenameClassWithNamespaceWithOutOfInlineMembers) {
-  std::string Before = R"(
-      namespace ns {
-      class Old {
-       public:
-        Old();
-        ~Old();
-
-        Old* next();
-
-       private:
-        Old* next_;
-      };
-
-      Old::Old() {}
-      Old::~Old() {}
-      Old* Old::next() { return next_; }
-      }  // namespace ns
-    )";
-  std::string Expected = R"(
-      namespace ns {
-      class ns::New {
-       public:
-        ns::New();
-        ~New();
-
-        New* next();
-
-       private:
-        New* next_;
-      };
-
-      New::ns::New() {}
-      New::~New() {}
-      New* New::next() { return next_; }
-      }  // namespace ns
-    )";
-  std::string After = runClangRenameOnCode(Before, "ns::Old", "ns::New");
-  CompareSnippets(Expected, After);
-}
-
-// FIXME: no prefix qualifiers being added to the definition.
-TEST_F(ClangRenameTest, RenameClassInInheritedConstructor) {
-  // `using Base::Base;` will generate an implicit constructor containing usage
-  // of `::ns::Old` which should not be matched.
-  std::string Before = R"(
-      namespace ns {
-      class Old {
-        int x;
-      };
-      class Base {
-       protected:
-        Old *moo_;
-       public:
-        Base(Old *moo) : moo_(moo) {}
-      };
-      class Derived : public Base {
-       public:
-         using Base::Base;
-      };
-      }  // namespace ns
-      int main() {
-        ::ns::Old foo;
-        ::ns::Derived d(&foo);
-        return 0;
-      })";
-  std::string Expected = R"(
-      namespace ns {
-      class ns::New {
-        int x;
-      };
-      class Base {
-       protected:
-        New *moo_;
-       public:
-        Base(New *moo) : moo_(moo) {}
-      };
-      class Derived : public Base {
-       public:
-         using Base::Base;
-      };
-      }  // namespace ns
-      int main() {
-        ::ns::New foo;
-        ::ns::Derived d(&foo);
-        return 0;
-      })";
-  std::string After = runClangRenameOnCode(Before, "ns::Old", "ns::New");
-  CompareSnippets(Expected, After);
-}
-
-TEST_F(ClangRenameTest, DontRenameReferencesInImplicitFunction) {
-  std::string Before = R"(
-      namespace ns {
-      class Old {
-      };
-      } // namespace ns
-      struct S {
-        int y;
-        ns::Old old;
-      };
-      void f() {
-        S s1, s2, s3;
-        // This causes an implicit assignment operator to be created.
-        s1 = s2 = s3;
-      }
-      )";
-  std::string Expected = R"(
-      namespace ns {
-      class ::new_ns::New {
-      };
-      } // namespace ns
-      struct S {
-        int y;
-        ::new_ns::New old;
-      };
-      void f() {
-        S s1, s2, s3;
-        // This causes an implicit assignment operator to be created.
-        s1 = s2 = s3;
-      }
-      )";
-  std::string After = runClangRenameOnCode(Before, "ns::Old", "::new_ns::New");
-  CompareSnippets(Expected, After);
-}
-
-// FIXME: no prefix qualifiers being adding to the definition.
-TEST_F(ClangRenameTest, ReferencesInLambdaFunctionParameters) {
-  std::string Before = R"(
-      template <class T>
-      class function;
-      template <class R, class... ArgTypes>
-      class function<R(ArgTypes...)> {
-      public:
-        template <typename Functor>
-        function(Functor f) {}
-
-        function() {}
-
-        R operator()(ArgTypes...) const {}
-      };
-
-      namespace ns {
-      class Old {};
-      void f() {
-        function<void(Old)> func;
-      }
-      }  // namespace ns)";
-  std::string Expected = R"(
-      template <class T>
-      class function;
-      template <class R, class... ArgTypes>
-      class function<R(ArgTypes...)> {
-      public:
-        template <typename Functor>
-        function(Functor f) {}
-
-        function() {}
-
-        R operator()(ArgTypes...) const {}
-      };
-
-      namespace ns {
-      class ::new_ns::New {};
-      void f() {
-        function<void(::new_ns::New)> func;
-      }
-      }  // namespace ns)";
-  std::string After = runClangRenameOnCode(Before, "ns::Old", "::new_ns::New");
-  CompareSnippets(Expected, After);
-}
-
-} // anonymous namespace
-} // namespace test
-} // namespace clang_rename
-} // namesdpace clang
diff --git a/unittests/clang-tidy/CMakeLists.txt b/unittests/clang-tidy/CMakeLists.txt
index d7d268b..0d9ab7c 100644
--- a/unittests/clang-tidy/CMakeLists.txt
+++ b/unittests/clang-tidy/CMakeLists.txt
@@ -25,6 +25,7 @@
   clangFrontend
   clangLex
   clangTidy
+  clangTidyAndroidModule
   clangTidyGoogleModule
   clangTidyLLVMModule
   clangTidyMiscModule
diff --git a/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp b/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp
index 0ee800d..5547f98 100644
--- a/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp
+++ b/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp
@@ -74,7 +74,7 @@
 }

 

 TEST(GlobList, Complex) {

-  GlobList Filter("*,-a.*, -b.*,   a.1.* ,-a.1.A.*,-..,-...,-..+,-*$, -*qwe* ");

+  GlobList Filter("*,-a.*, -b.*, \r  \n  a.1.* ,-a.1.A.*,-..,-...,-..+,-*$, -*qwe* ");

 

   EXPECT_TRUE(Filter.contains("aaa"));

   EXPECT_TRUE(Filter.contains("qqq"));

diff --git a/unittests/clang-tidy/ReadabilityModuleTest.cpp b/unittests/clang-tidy/ReadabilityModuleTest.cpp
index e79d024..a0eca16 100644
--- a/unittests/clang-tidy/ReadabilityModuleTest.cpp
+++ b/unittests/clang-tidy/ReadabilityModuleTest.cpp
@@ -487,11 +487,17 @@
   ClangTidyOptions Opts;
   Opts.CheckOptions["test-check-0.ShortStatementLines"] = "1";
 
-  EXPECT_NO_CHANGES_WITH_OPTS(BracesAroundStatementsCheck, Opts,
-                              "const char *f() {\n"
+  StringRef Input = "const char *f() {\n"
                               "  if (true) return \"\";\n"
                               "  return \"abc\";\n"
-                              "}\n");
+                              "}\n";
+  EXPECT_NO_CHANGES_WITH_OPTS(BracesAroundStatementsCheck, Opts, Input);
+  EXPECT_EQ("const char *f() {\n"
+            "  if (true) { return \"\";\n"
+            "}\n"
+            "  return \"abc\";\n"
+            "}\n",
+            runCheckOnCode<BracesAroundStatementsCheck>(Input));
 }
 
 } // namespace test
diff --git a/unittests/clangd/ClangdTests.cpp b/unittests/clangd/ClangdTests.cpp
index 1e4655b..a6523d8 100644
--- a/unittests/clangd/ClangdTests.cpp
+++ b/unittests/clangd/ClangdTests.cpp
@@ -7,7 +7,9 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "ClangdLSPServer.h"
 #include "ClangdServer.h"
+#include "Logger.h"
 #include "clang/Basic/VirtualFileSystem.h"
 #include "clang/Config/config.h"
 #include "llvm/ADT/SmallVector.h"
@@ -17,8 +19,11 @@
 #include "llvm/Support/Regex.h"
 #include "gtest/gtest.h"
 #include <algorithm>
+#include <chrono>
 #include <iostream>
+#include <random>
 #include <string>
+#include <thread>
 #include <vector>
 
 namespace clang {
@@ -130,17 +135,28 @@
 namespace clangd {
 namespace {
 
+// Don't wait for async ops in clangd test more than that to avoid blocking
+// indefinitely in case of bugs.
+static const std::chrono::seconds DefaultFutureTimeout =
+    std::chrono::seconds(10);
+
+static bool diagsContainErrors(ArrayRef<DiagWithFixIts> Diagnostics) {
+  for (const auto &DiagAndFixIts : Diagnostics) {
+    // FIXME: severities returned by clangd should have a descriptive
+    // diagnostic severity enum
+    const int ErrorSeverity = 1;
+    if (DiagAndFixIts.Diag.severity == ErrorSeverity)
+      return true;
+  }
+  return false;
+}
+
 class ErrorCheckingDiagConsumer : public DiagnosticsConsumer {
 public:
-  void onDiagnosticsReady(PathRef File,
-                          Tagged<std::vector<DiagWithFixIts>> Diagnostics) override {
-    bool HadError = false;
-    for (const auto &DiagAndFixIts : Diagnostics.Value) {
-      // FIXME: severities returned by clangd should have a descriptive
-      // diagnostic severity enum
-      const int ErrorSeverity = 1;
-      HadError = DiagAndFixIts.Diag.severity == ErrorSeverity;
-    }
+  void
+  onDiagnosticsReady(PathRef File,
+                     Tagged<std::vector<DiagWithFixIts>> Diagnostics) override {
+    bool HadError = diagsContainErrors(Diagnostics.Value);
 
     std::lock_guard<std::mutex> Lock(Mutex);
     HadErrorInLastDiags = HadError;
@@ -152,9 +168,7 @@
     return HadErrorInLastDiags;
   }
 
-  VFSTag lastVFSTag() {
-    return LastVFSTag;
-  }
+  VFSTag lastVFSTag() { return LastVFSTag; }
 
 private:
   std::mutex Mutex;
@@ -164,30 +178,74 @@
 
 class MockCompilationDatabase : public GlobalCompilationDatabase {
 public:
+  MockCompilationDatabase(bool AddFreestandingFlag) {
+    // We have to add -ffreestanding to VFS-specific tests to avoid errors on
+    // implicit includes of stdc-predef.h.
+    if (AddFreestandingFlag)
+      ExtraClangFlags.push_back("-ffreestanding");
+  }
+
   std::vector<tooling::CompileCommand>
   getCompileCommands(PathRef File) override {
-    return {};
+    if (ExtraClangFlags.empty())
+      return {};
+
+    std::vector<std::string> CommandLine;
+    CommandLine.reserve(3 + ExtraClangFlags.size());
+    CommandLine.insert(CommandLine.end(), {"clang", "-fsyntax-only"});
+    CommandLine.insert(CommandLine.end(), ExtraClangFlags.begin(),
+                       ExtraClangFlags.end());
+    CommandLine.push_back(File.str());
+
+    return {tooling::CompileCommand(llvm::sys::path::parent_path(File),
+                                    llvm::sys::path::filename(File),
+                                    CommandLine, "")};
   }
+
+  std::vector<std::string> ExtraClangFlags;
+};
+
+IntrusiveRefCntPtr<vfs::FileSystem>
+buildTestFS(llvm::StringMap<std::string> const &Files) {
+  IntrusiveRefCntPtr<vfs::InMemoryFileSystem> MemFS(
+      new vfs::InMemoryFileSystem);
+  for (auto &FileAndContents : Files)
+    MemFS->addFile(FileAndContents.first(), time_t(),
+                   llvm::MemoryBuffer::getMemBuffer(FileAndContents.second,
+                                                    FileAndContents.first()));
+
+  auto OverlayFS = IntrusiveRefCntPtr<vfs::OverlayFileSystem>(
+      new vfs::OverlayFileSystem(vfs::getTempOnlyFS()));
+  OverlayFS->pushOverlay(std::move(MemFS));
+  return OverlayFS;
+}
+
+class ConstantFSProvider : public FileSystemProvider {
+public:
+  ConstantFSProvider(IntrusiveRefCntPtr<vfs::FileSystem> FS,
+                     VFSTag Tag = VFSTag())
+      : FS(std::move(FS)), Tag(std::move(Tag)) {}
+
+  Tagged<IntrusiveRefCntPtr<vfs::FileSystem>>
+  getTaggedFileSystem(PathRef File) override {
+    return make_tagged(FS, Tag);
+  }
+
+private:
+  IntrusiveRefCntPtr<vfs::FileSystem> FS;
+  VFSTag Tag;
 };
 
 class MockFSProvider : public FileSystemProvider {
 public:
   Tagged<IntrusiveRefCntPtr<vfs::FileSystem>>
   getTaggedFileSystem(PathRef File) override {
-    IntrusiveRefCntPtr<vfs::InMemoryFileSystem> MemFS(
-        new vfs::InMemoryFileSystem);
-    if (ExpectedFile)
+    if (ExpectedFile) {
       EXPECT_EQ(*ExpectedFile, File);
+    }
 
-    for (auto &FileAndContents : Files)
-      MemFS->addFile(FileAndContents.first(), time_t(),
-                     llvm::MemoryBuffer::getMemBuffer(FileAndContents.second,
-                                                      FileAndContents.first()));
-
-    auto OverlayFS = IntrusiveRefCntPtr<vfs::OverlayFileSystem>(
-        new vfs::OverlayFileSystem(vfs::getTempOnlyFS()));
-    OverlayFS->pushOverlay(std::move(MemFS));
-    return make_tagged(OverlayFS, Tag);
+    auto FS = buildTestFS(Files);
+    return make_tagged(FS, Tag);
   }
 
   llvm::Optional<SmallString<32>> ExpectedFile;
@@ -245,9 +303,10 @@
       bool ExpectErrors = false) {
     MockFSProvider FS;
     ErrorCheckingDiagConsumer DiagConsumer;
-    MockCompilationDatabase CDB;
-    ClangdServer Server(CDB, DiagConsumer, FS,
-                        /*RunSynchronously=*/false);
+    MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
+    ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
+                        /*SnippetCompletions=*/false,
+                        EmptyLogger::getInstance());
     for (const auto &FileWithContents : ExtraFiles)
       FS.Files[getVirtualTestFilePath(FileWithContents.first)] =
           FileWithContents.second;
@@ -255,9 +314,16 @@
     auto SourceFilename = getVirtualTestFilePath(SourceFileRelPath);
 
     FS.ExpectedFile = SourceFilename;
-    Server.addDocument(SourceFilename, SourceContents);
+
+    // Have to sync reparses because requests are processed on the calling
+    // thread.
+    auto AddDocFuture = Server.addDocument(SourceFilename, SourceContents);
 
     auto Result = dumpASTWithoutMemoryLocs(Server, SourceFilename);
+
+    // Wait for reparse to finish before checking for errors.
+    EXPECT_EQ(AddDocFuture.wait_for(DefaultFutureTimeout),
+              std::future_status::ready);
     EXPECT_EQ(ExpectErrors, DiagConsumer.hadErrorInLastDiags());
     return Result;
   }
@@ -301,9 +367,9 @@
 TEST_F(ClangdVFSTest, Reparse) {
   MockFSProvider FS;
   ErrorCheckingDiagConsumer DiagConsumer;
-  MockCompilationDatabase CDB;
-  ClangdServer Server(CDB, DiagConsumer, FS,
-                      /*RunSynchronously=*/false);
+  MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
+  ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
+                      /*SnippetCompletions=*/false, EmptyLogger::getInstance());
 
   const auto SourceContents = R"cpp(
 #include "foo.h"
@@ -317,16 +383,25 @@
   FS.Files[FooCpp] = SourceContents;
   FS.ExpectedFile = FooCpp;
 
-  Server.addDocument(FooCpp, SourceContents);
+  // To sync reparses before checking for errors.
+  std::future<void> ParseFuture;
+
+  ParseFuture = Server.addDocument(FooCpp, SourceContents);
   auto DumpParse1 = dumpASTWithoutMemoryLocs(Server, FooCpp);
+  ASSERT_EQ(ParseFuture.wait_for(DefaultFutureTimeout),
+            std::future_status::ready);
   EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
 
-  Server.addDocument(FooCpp, "");
+  ParseFuture = Server.addDocument(FooCpp, "");
   auto DumpParseEmpty = dumpASTWithoutMemoryLocs(Server, FooCpp);
+  ASSERT_EQ(ParseFuture.wait_for(DefaultFutureTimeout),
+            std::future_status::ready);
   EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
 
-  Server.addDocument(FooCpp, SourceContents);
+  ParseFuture = Server.addDocument(FooCpp, SourceContents);
   auto DumpParse2 = dumpASTWithoutMemoryLocs(Server, FooCpp);
+  ASSERT_EQ(ParseFuture.wait_for(DefaultFutureTimeout),
+            std::future_status::ready);
   EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
 
   EXPECT_EQ(DumpParse1, DumpParse2);
@@ -336,10 +411,10 @@
 TEST_F(ClangdVFSTest, ReparseOnHeaderChange) {
   MockFSProvider FS;
   ErrorCheckingDiagConsumer DiagConsumer;
-  MockCompilationDatabase CDB;
+  MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
 
-  ClangdServer Server(CDB, DiagConsumer, FS,
-                      /*RunSynchronously=*/false);
+  ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
+                      /*SnippetCompletions=*/false, EmptyLogger::getInstance());
 
   const auto SourceContents = R"cpp(
 #include "foo.h"
@@ -353,18 +428,27 @@
   FS.Files[FooCpp] = SourceContents;
   FS.ExpectedFile = FooCpp;
 
-  Server.addDocument(FooCpp, SourceContents);
+  // To sync reparses before checking for errors.
+  std::future<void> ParseFuture;
+
+  ParseFuture = Server.addDocument(FooCpp, SourceContents);
   auto DumpParse1 = dumpASTWithoutMemoryLocs(Server, FooCpp);
+  ASSERT_EQ(ParseFuture.wait_for(DefaultFutureTimeout),
+            std::future_status::ready);
   EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
 
   FS.Files[FooH] = "";
-  Server.forceReparse(FooCpp);
+  ParseFuture = Server.forceReparse(FooCpp);
   auto DumpParseDifferent = dumpASTWithoutMemoryLocs(Server, FooCpp);
+  ASSERT_EQ(ParseFuture.wait_for(DefaultFutureTimeout),
+            std::future_status::ready);
   EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
 
   FS.Files[FooH] = "int a;";
-  Server.forceReparse(FooCpp);
+  ParseFuture = Server.forceReparse(FooCpp);
   auto DumpParse2 = dumpASTWithoutMemoryLocs(Server, FooCpp);
+  EXPECT_EQ(ParseFuture.wait_for(DefaultFutureTimeout),
+            std::future_status::ready);
   EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
 
   EXPECT_EQ(DumpParse1, DumpParse2);
@@ -374,24 +458,133 @@
 TEST_F(ClangdVFSTest, CheckVersions) {
   MockFSProvider FS;
   ErrorCheckingDiagConsumer DiagConsumer;
-  MockCompilationDatabase CDB;
+  MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
+  // Run ClangdServer synchronously.
   ClangdServer Server(CDB, DiagConsumer, FS,
-                      /*RunSynchronously=*/true);
+                      /*AsyncThreadsCount=*/0, /*SnippetCompletions=*/false,
+                      EmptyLogger::getInstance());
 
   auto FooCpp = getVirtualTestFilePath("foo.cpp");
   const auto SourceContents = "int a;";
   FS.Files[FooCpp] = SourceContents;
   FS.ExpectedFile = FooCpp;
 
+  // No need to sync reparses, because requests are processed on the calling
+  // thread.
   FS.Tag = "123";
   Server.addDocument(FooCpp, SourceContents);
+  EXPECT_EQ(Server.codeComplete(FooCpp, Position{0, 0}).get().Tag, FS.Tag);
   EXPECT_EQ(DiagConsumer.lastVFSTag(), FS.Tag);
-  EXPECT_EQ(Server.codeComplete(FooCpp, Position{0, 0}).Tag, FS.Tag);
 
   FS.Tag = "321";
   Server.addDocument(FooCpp, SourceContents);
   EXPECT_EQ(DiagConsumer.lastVFSTag(), FS.Tag);
-  EXPECT_EQ(Server.codeComplete(FooCpp, Position{0, 0}).Tag, FS.Tag);
+  EXPECT_EQ(Server.codeComplete(FooCpp, Position{0, 0}).get().Tag, FS.Tag);
+}
+
+// Only enable this test on Unix
+#ifdef LLVM_ON_UNIX
+TEST_F(ClangdVFSTest, SearchLibDir) {
+  // Checks that searches for GCC installation is done through vfs.
+  MockFSProvider FS;
+  ErrorCheckingDiagConsumer DiagConsumer;
+  MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
+  CDB.ExtraClangFlags.insert(CDB.ExtraClangFlags.end(),
+                             {"-xc++", "-target", "x86_64-linux-unknown",
+                              "-m64", "--gcc-toolchain=/randomusr",
+                              "-stdlib=libstdc++"});
+  // Run ClangdServer synchronously.
+  ClangdServer Server(CDB, DiagConsumer, FS,
+                      /*AsyncThreadsCount=*/0, /*SnippetCompletions=*/false,
+                      EmptyLogger::getInstance());
+
+  // Just a random gcc version string
+  SmallString<8> Version("4.9.3");
+
+  // A lib dir for gcc installation
+  SmallString<64> LibDir("/randomusr/lib/gcc/x86_64-linux-gnu");
+  llvm::sys::path::append(LibDir, Version);
+
+  // Put crtbegin.o into LibDir/64 to trick clang into thinking there's a gcc
+  // installation there.
+  SmallString<64> DummyLibFile;
+  llvm::sys::path::append(DummyLibFile, LibDir, "64", "crtbegin.o");
+  FS.Files[DummyLibFile] = "";
+
+  SmallString<64> IncludeDir("/randomusr/include/c++");
+  llvm::sys::path::append(IncludeDir, Version);
+
+  SmallString<64> StringPath;
+  llvm::sys::path::append(StringPath, IncludeDir, "string");
+  FS.Files[StringPath] = "class mock_string {};";
+
+  auto FooCpp = getVirtualTestFilePath("foo.cpp");
+  const auto SourceContents = R"cpp(
+#include <string>
+mock_string x;
+)cpp";
+  FS.Files[FooCpp] = SourceContents;
+
+  // No need to sync reparses, because requests are processed on the calling
+  // thread.
+  Server.addDocument(FooCpp, SourceContents);
+  EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
+
+  const auto SourceContentsWithError = R"cpp(
+#include <string>
+std::string x;
+)cpp";
+  Server.addDocument(FooCpp, SourceContentsWithError);
+  EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
+}
+#endif // LLVM_ON_UNIX
+
+TEST_F(ClangdVFSTest, ForceReparseCompileCommand) {
+  MockFSProvider FS;
+  ErrorCheckingDiagConsumer DiagConsumer;
+  MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
+  ClangdServer Server(CDB, DiagConsumer, FS,
+                      /*AsyncThreadsCount=*/0, /*SnippetCompletions=*/false,
+                      EmptyLogger::getInstance());
+  // No need to sync reparses, because reparses are performed on the calling
+  // thread to true.
+
+  auto FooCpp = getVirtualTestFilePath("foo.cpp");
+  const auto SourceContents1 = R"cpp(
+template <class T>
+struct foo { T x; };
+)cpp";
+  const auto SourceContents2 = R"cpp(
+template <class T>
+struct bar { T x; };
+)cpp";
+
+  FS.Files[FooCpp] = "";
+  FS.ExpectedFile = FooCpp;
+
+  // First parse files in C mode and check they produce errors.
+  CDB.ExtraClangFlags = {"-xc"};
+  Server.addDocument(FooCpp, SourceContents1);
+  EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
+  Server.addDocument(FooCpp, SourceContents2);
+  EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
+
+  // Now switch to C++ mode.
+  CDB.ExtraClangFlags = {"-xc++"};
+  // Currently, addDocument never checks if CompileCommand has changed, so we
+  // expect to see the errors.
+  Server.addDocument(FooCpp, SourceContents1);
+  EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
+  Server.addDocument(FooCpp, SourceContents2);
+  EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
+  // But forceReparse should reparse the file with proper flags.
+  Server.forceReparse(FooCpp);
+  EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
+  // Subsequent addDocument calls should finish without errors too.
+  Server.addDocument(FooCpp, SourceContents1);
+  EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
+  Server.addDocument(FooCpp, SourceContents2);
+  EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
 }
 
 class ClangdCompletionTest : public ClangdVFSTest {
@@ -408,10 +601,10 @@
 TEST_F(ClangdCompletionTest, CheckContentsOverride) {
   MockFSProvider FS;
   ErrorCheckingDiagConsumer DiagConsumer;
-  MockCompilationDatabase CDB;
+  MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
 
-  ClangdServer Server(CDB, DiagConsumer, FS,
-                      /*RunSynchronously=*/false);
+  ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
+                      /*SnippetCompletions=*/false, EmptyLogger::getInstance());
 
   auto FooCpp = getVirtualTestFilePath("foo.cpp");
   const auto SourceContents = R"cpp(
@@ -432,11 +625,13 @@
   FS.Files[FooCpp] = SourceContents;
   FS.ExpectedFile = FooCpp;
 
+  // No need to sync reparses here as there are no asserts on diagnostics (or
+  // other async operations).
   Server.addDocument(FooCpp, SourceContents);
 
   {
     auto CodeCompletionResults1 =
-        Server.codeComplete(FooCpp, CompletePos, None).Value;
+        Server.codeComplete(FooCpp, CompletePos, None).get().Value;
     EXPECT_TRUE(ContainsItem(CodeCompletionResults1, "aba"));
     EXPECT_FALSE(ContainsItem(CodeCompletionResults1, "cbc"));
   }
@@ -446,6 +641,7 @@
         Server
             .codeComplete(FooCpp, CompletePos,
                           StringRef(OverridenSourceContents))
+            .get()
             .Value;
     EXPECT_TRUE(ContainsItem(CodeCompletionResultsOverriden, "cbc"));
     EXPECT_FALSE(ContainsItem(CodeCompletionResultsOverriden, "aba"));
@@ -453,11 +649,403 @@
 
   {
     auto CodeCompletionResults2 =
-        Server.codeComplete(FooCpp, CompletePos, None).Value;
+        Server.codeComplete(FooCpp, CompletePos, None).get().Value;
     EXPECT_TRUE(ContainsItem(CodeCompletionResults2, "aba"));
     EXPECT_FALSE(ContainsItem(CodeCompletionResults2, "cbc"));
   }
 }
 
+class ClangdThreadingTest : public ClangdVFSTest {};
+
+TEST_F(ClangdThreadingTest, StressTest) {
+  // Without 'static' clang gives an error for a usage inside TestDiagConsumer.
+  static const unsigned FilesCount = 5;
+  const unsigned RequestsCount = 500;
+  // Blocking requests wait for the parsing to complete, they slow down the test
+  // dramatically, so they are issued rarely. Each
+  // BlockingRequestInterval-request will be a blocking one.
+  const unsigned BlockingRequestInterval = 40;
+
+  const auto SourceContentsWithoutErrors = R"cpp(
+int a;
+int b;
+int c;
+int d;
+)cpp";
+
+  const auto SourceContentsWithErrors = R"cpp(
+int a = x;
+int b;
+int c;
+int d;
+)cpp";
+
+  // Giving invalid line and column number should not crash ClangdServer, but
+  // just to make sure we're sometimes hitting the bounds inside the file we
+  // limit the intervals of line and column number that are generated.
+  unsigned MaxLineForFileRequests = 7;
+  unsigned MaxColumnForFileRequests = 10;
+
+  std::vector<SmallString<32>> FilePaths;
+  FilePaths.reserve(FilesCount);
+  for (unsigned I = 0; I < FilesCount; ++I)
+    FilePaths.push_back(getVirtualTestFilePath(std::string("Foo") +
+                                               std::to_string(I) + ".cpp"));
+  // Mark all of those files as existing.
+  llvm::StringMap<std::string> FileContents;
+  for (auto &&FilePath : FilePaths)
+    FileContents[FilePath] = "";
+
+  ConstantFSProvider FS(buildTestFS(FileContents));
+
+  struct FileStat {
+    unsigned HitsWithoutErrors = 0;
+    unsigned HitsWithErrors = 0;
+    bool HadErrorsInLastDiags = false;
+  };
+
+  class TestDiagConsumer : public DiagnosticsConsumer {
+  public:
+    TestDiagConsumer() : Stats(FilesCount, FileStat()) {}
+
+    void onDiagnosticsReady(
+        PathRef File,
+        Tagged<std::vector<DiagWithFixIts>> Diagnostics) override {
+      StringRef FileIndexStr = llvm::sys::path::stem(File);
+      ASSERT_TRUE(FileIndexStr.consume_front("Foo"));
+
+      unsigned long FileIndex = std::stoul(FileIndexStr.str());
+
+      bool HadError = diagsContainErrors(Diagnostics.Value);
+
+      std::lock_guard<std::mutex> Lock(Mutex);
+      if (HadError)
+        Stats[FileIndex].HitsWithErrors++;
+      else
+        Stats[FileIndex].HitsWithoutErrors++;
+      Stats[FileIndex].HadErrorsInLastDiags = HadError;
+    }
+
+    std::vector<FileStat> takeFileStats() {
+      std::lock_guard<std::mutex> Lock(Mutex);
+      return std::move(Stats);
+    }
+
+  private:
+    std::mutex Mutex;
+    std::vector<FileStat> Stats;
+  };
+
+  struct RequestStats {
+    unsigned RequestsWithoutErrors = 0;
+    unsigned RequestsWithErrors = 0;
+    bool LastContentsHadErrors = false;
+    bool FileIsRemoved = true;
+    std::future<void> LastRequestFuture;
+  };
+
+  std::vector<RequestStats> ReqStats;
+  ReqStats.reserve(FilesCount);
+  for (unsigned FileIndex = 0; FileIndex < FilesCount; ++FileIndex)
+    ReqStats.emplace_back();
+
+  TestDiagConsumer DiagConsumer;
+  {
+    MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
+    ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
+                        /*SnippetCompletions=*/false,
+                        EmptyLogger::getInstance());
+
+    // Prepare some random distributions for the test.
+    std::random_device RandGen;
+
+    std::uniform_int_distribution<unsigned> FileIndexDist(0, FilesCount - 1);
+    // Pass a text that contains compiler errors to addDocument in about 20% of
+    // all requests.
+    std::bernoulli_distribution ShouldHaveErrorsDist(0.2);
+    // Line and Column numbers for requests that need them.
+    std::uniform_int_distribution<int> LineDist(0, MaxLineForFileRequests);
+    std::uniform_int_distribution<int> ColumnDist(0, MaxColumnForFileRequests);
+
+    // Some helpers.
+    auto UpdateStatsOnAddDocument = [&](unsigned FileIndex, bool HadErrors,
+                                        std::future<void> Future) {
+      auto &Stats = ReqStats[FileIndex];
+
+      if (HadErrors)
+        ++Stats.RequestsWithErrors;
+      else
+        ++Stats.RequestsWithoutErrors;
+      Stats.LastContentsHadErrors = HadErrors;
+      Stats.FileIsRemoved = false;
+      Stats.LastRequestFuture = std::move(Future);
+    };
+
+    auto UpdateStatsOnRemoveDocument = [&](unsigned FileIndex,
+                                           std::future<void> Future) {
+      auto &Stats = ReqStats[FileIndex];
+
+      Stats.FileIsRemoved = true;
+      Stats.LastRequestFuture = std::move(Future);
+    };
+
+    auto UpdateStatsOnForceReparse = [&](unsigned FileIndex,
+                                         std::future<void> Future) {
+      auto &Stats = ReqStats[FileIndex];
+
+      Stats.LastRequestFuture = std::move(Future);
+      if (Stats.LastContentsHadErrors)
+        ++Stats.RequestsWithErrors;
+      else
+        ++Stats.RequestsWithoutErrors;
+    };
+
+    auto AddDocument = [&](unsigned FileIndex) {
+      bool ShouldHaveErrors = ShouldHaveErrorsDist(RandGen);
+      auto Future = Server.addDocument(
+          FilePaths[FileIndex], ShouldHaveErrors ? SourceContentsWithErrors
+                                                 : SourceContentsWithoutErrors);
+      UpdateStatsOnAddDocument(FileIndex, ShouldHaveErrors, std::move(Future));
+    };
+
+    // Various requests that we would randomly run.
+    auto AddDocumentRequest = [&]() {
+      unsigned FileIndex = FileIndexDist(RandGen);
+      AddDocument(FileIndex);
+    };
+
+    auto ForceReparseRequest = [&]() {
+      unsigned FileIndex = FileIndexDist(RandGen);
+      // Make sure we don't violate the ClangdServer's contract.
+      if (ReqStats[FileIndex].FileIsRemoved)
+        AddDocument(FileIndex);
+
+      auto Future = Server.forceReparse(FilePaths[FileIndex]);
+      UpdateStatsOnForceReparse(FileIndex, std::move(Future));
+    };
+
+    auto RemoveDocumentRequest = [&]() {
+      unsigned FileIndex = FileIndexDist(RandGen);
+      // Make sure we don't violate the ClangdServer's contract.
+      if (ReqStats[FileIndex].FileIsRemoved)
+        AddDocument(FileIndex);
+
+      auto Future = Server.removeDocument(FilePaths[FileIndex]);
+      UpdateStatsOnRemoveDocument(FileIndex, std::move(Future));
+    };
+
+    auto CodeCompletionRequest = [&]() {
+      unsigned FileIndex = FileIndexDist(RandGen);
+      // Make sure we don't violate the ClangdServer's contract.
+      if (ReqStats[FileIndex].FileIsRemoved)
+        AddDocument(FileIndex);
+
+      Position Pos{LineDist(RandGen), ColumnDist(RandGen)};
+      // FIXME(ibiryukov): Also test async completion requests.
+      // Simply putting CodeCompletion into async requests now would make
+      // tests slow, since there's no way to cancel previous completion
+      // requests as opposed to AddDocument/RemoveDocument, which are implicitly
+      // cancelled by any subsequent AddDocument/RemoveDocument request to the
+      // same file.
+      Server.codeComplete(FilePaths[FileIndex], Pos).wait();
+    };
+
+    auto FindDefinitionsRequest = [&]() {
+      unsigned FileIndex = FileIndexDist(RandGen);
+      // Make sure we don't violate the ClangdServer's contract.
+      if (ReqStats[FileIndex].FileIsRemoved)
+        AddDocument(FileIndex);
+
+      Position Pos{LineDist(RandGen), ColumnDist(RandGen)};
+      Server.findDefinitions(FilePaths[FileIndex], Pos);
+    };
+
+    std::vector<std::function<void()>> AsyncRequests = {
+        AddDocumentRequest, ForceReparseRequest, RemoveDocumentRequest};
+    std::vector<std::function<void()>> BlockingRequests = {
+        CodeCompletionRequest, FindDefinitionsRequest};
+
+    // Bash requests to ClangdServer in a loop.
+    std::uniform_int_distribution<int> AsyncRequestIndexDist(
+        0, AsyncRequests.size() - 1);
+    std::uniform_int_distribution<int> BlockingRequestIndexDist(
+        0, BlockingRequests.size() - 1);
+    for (unsigned I = 1; I <= RequestsCount; ++I) {
+      if (I % BlockingRequestInterval != 0) {
+        // Issue an async request most of the time. It should be fast.
+        unsigned RequestIndex = AsyncRequestIndexDist(RandGen);
+        AsyncRequests[RequestIndex]();
+      } else {
+        // Issue a blocking request once in a while.
+        auto RequestIndex = BlockingRequestIndexDist(RandGen);
+        BlockingRequests[RequestIndex]();
+      }
+    }
+
+    // Wait for last requests to finish.
+    for (auto &ReqStat : ReqStats) {
+      if (!ReqStat.LastRequestFuture.valid())
+        continue; // We never ran any requests for this file.
+
+      // Future should be ready much earlier than in 5 seconds, the timeout is
+      // there to check we won't wait indefinitely.
+      ASSERT_EQ(ReqStat.LastRequestFuture.wait_for(std::chrono::seconds(5)),
+                std::future_status::ready);
+    }
+  } // Wait for ClangdServer to shutdown before proceeding.
+
+  // Check some invariants about the state of the program.
+  std::vector<FileStat> Stats = DiagConsumer.takeFileStats();
+  for (unsigned I = 0; I < FilesCount; ++I) {
+    if (!ReqStats[I].FileIsRemoved) {
+      ASSERT_EQ(Stats[I].HadErrorsInLastDiags,
+                ReqStats[I].LastContentsHadErrors);
+    }
+
+    ASSERT_LE(Stats[I].HitsWithErrors, ReqStats[I].RequestsWithErrors);
+    ASSERT_LE(Stats[I].HitsWithoutErrors, ReqStats[I].RequestsWithoutErrors);
+  }
+}
+
+TEST_F(ClangdVFSTest, CheckSourceHeaderSwitch) {
+  MockFSProvider FS;
+  ErrorCheckingDiagConsumer DiagConsumer;
+  MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
+
+  ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
+                      /*SnippetCompletions=*/false, EmptyLogger::getInstance());
+
+  auto SourceContents = R"cpp(
+  #include "foo.h"
+  int b = a;
+  )cpp";
+
+  auto FooCpp = getVirtualTestFilePath("foo.cpp");
+  auto FooH = getVirtualTestFilePath("foo.h");
+  auto Invalid = getVirtualTestFilePath("main.cpp");
+
+  FS.Files[FooCpp] = SourceContents;
+  FS.Files[FooH] = "int a;";
+  FS.Files[Invalid] = "int main() { \n return 0; \n }";
+
+  llvm::Optional<Path> PathResult = Server.switchSourceHeader(FooCpp);
+  EXPECT_TRUE(PathResult.hasValue());
+  ASSERT_EQ(PathResult.getValue(), FooH);
+
+  PathResult = Server.switchSourceHeader(FooH);
+  EXPECT_TRUE(PathResult.hasValue());
+  ASSERT_EQ(PathResult.getValue(), FooCpp);
+
+  SourceContents = R"c(
+  #include "foo.HH"
+  int b = a;
+  )c";
+
+  // Test with header file in capital letters and different extension, source
+  // file with different extension
+  auto FooC = getVirtualTestFilePath("bar.c");
+  auto FooHH = getVirtualTestFilePath("bar.HH");
+
+  FS.Files[FooC] = SourceContents;
+  FS.Files[FooHH] = "int a;";
+
+  PathResult = Server.switchSourceHeader(FooC);
+  EXPECT_TRUE(PathResult.hasValue());
+  ASSERT_EQ(PathResult.getValue(), FooHH);
+
+  // Test with both capital letters
+  auto Foo2C = getVirtualTestFilePath("foo2.C");
+  auto Foo2HH = getVirtualTestFilePath("foo2.HH");
+  FS.Files[Foo2C] = SourceContents;
+  FS.Files[Foo2HH] = "int a;";
+
+  PathResult = Server.switchSourceHeader(Foo2C);
+  EXPECT_TRUE(PathResult.hasValue());
+  ASSERT_EQ(PathResult.getValue(), Foo2HH);
+
+  // Test with source file as capital letter and .hxx header file
+  auto Foo3C = getVirtualTestFilePath("foo3.C");
+  auto Foo3HXX = getVirtualTestFilePath("foo3.hxx");
+
+  SourceContents = R"c(
+  #include "foo3.hxx"
+  int b = a;
+  )c";
+
+  FS.Files[Foo3C] = SourceContents;
+  FS.Files[Foo3HXX] = "int a;";
+
+  PathResult = Server.switchSourceHeader(Foo3C);
+  EXPECT_TRUE(PathResult.hasValue());
+  ASSERT_EQ(PathResult.getValue(), Foo3HXX);
+
+  // Test if asking for a corresponding file that doesn't exist returns an empty
+  // string.
+  PathResult = Server.switchSourceHeader(Invalid);
+  EXPECT_FALSE(PathResult.hasValue());
+}
+
+TEST_F(ClangdThreadingTest, NoConcurrentDiagnostics) {
+  class NoConcurrentAccessDiagConsumer : public DiagnosticsConsumer {
+  public:
+    NoConcurrentAccessDiagConsumer(std::promise<void> StartSecondReparse)
+        : StartSecondReparse(std::move(StartSecondReparse)) {}
+
+    void onDiagnosticsReady(
+        PathRef File,
+        Tagged<std::vector<DiagWithFixIts>> Diagnostics) override {
+
+      std::unique_lock<std::mutex> Lock(Mutex, std::try_to_lock_t());
+      ASSERT_TRUE(Lock.owns_lock())
+          << "Detected concurrent onDiagnosticsReady calls for the same file.";
+      if (FirstRequest) {
+        FirstRequest = false;
+        StartSecondReparse.set_value();
+        // Sleep long enough for the second request to be processed.
+        std::this_thread::sleep_for(std::chrono::milliseconds(50));
+      }
+    }
+
+  private:
+    std::mutex Mutex;
+    bool FirstRequest = true;
+    std::promise<void> StartSecondReparse;
+  };
+
+  const auto SourceContentsWithoutErrors = R"cpp(
+int a;
+int b;
+int c;
+int d;
+)cpp";
+
+  const auto SourceContentsWithErrors = R"cpp(
+int a = x;
+int b;
+int c;
+int d;
+)cpp";
+
+  auto FooCpp = getVirtualTestFilePath("foo.cpp");
+  llvm::StringMap<std::string> FileContents;
+  FileContents[FooCpp] = "";
+  ConstantFSProvider FS(buildTestFS(FileContents));
+
+  std::promise<void> StartSecondReparsePromise;
+  std::future<void> StartSecondReparse = StartSecondReparsePromise.get_future();
+
+  NoConcurrentAccessDiagConsumer DiagConsumer(
+      std::move(StartSecondReparsePromise));
+
+  MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
+  ClangdServer Server(CDB, DiagConsumer, FS, 4, /*SnippetCompletions=*/false,
+                      EmptyLogger::getInstance());
+  Server.addDocument(FooCpp, SourceContentsWithErrors);
+  StartSecondReparse.wait();
+
+  auto Future = Server.addDocument(FooCpp, SourceContentsWithoutErrors);
+  Future.wait();
+}
+
 } // namespace clangd
 } // namespace clang