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